一、预处理指令

//宏名 值; #define //宏的变量名全部是大写,结尾不需要写分号 #define COUNT 6 //还可以取消宏的定义 #undef COUNT 编译器的作用是将原代码文件中的代码翻译成机器可执行的代码,也就是0和1,而预处理指令会在编译器翻译代码之前执行带参数的宏定义
/* 一定要加括号,否则会出现意想不到的结果比如像下面这样调用 sum(10,10) * sum(10,10); 相当于下面: 10+10*10+10 这样替换过后改变了运算顺序,也就改变了预期的运算结果 所以一定要把所有变量都加上括号 再比如平方的例子一定要像下面这样写,每个形参都要加上括号 #define Square(a)((a)*(a)) */ #define sum(v1,v2)((v1)+(v2)) int main(void){ int result = sum(11,10); printf("result=%d\n",result); //输出了21 return 0; } 宏定义只是单纯的把左边的定义(比如:sum(v1,v2))替换成右边的(比如:(v1)+(v2)),不做任何运算在常见的比较简单的函数可以使用宏定义,这样比函数效率要高条件编译
#define A 10 int main(){ //条件编译判断如果用到常量值,比如下面的A //则必须得是通过宏定义的,因为在编译前已经进行了判断 //条件的括号可以省略 #if (A == 10) printf("a = 10\n"); #elif (A == 5) printf("a = 5\n"); #else printf("a is other number\n"); #endif //一定要有#endif结尾 return 0; } 防止文件多次被包含
当进行多文件开发时,某些函数功能,需要在.h文件中进行声明,还要将.h文件包含到某个文件中,当代码量过大时,有可能发生多次包含,这虽然不会产生错误,但是会影响性能,所以在头文件中可以利用条件编译,防止多次包含头文件,例如像下面这样定义头文件:
/* 解释下面的写法的逻辑: 如果没有定义宏 ABC 那么就定义一个宏ABC 并且声明sum()函数 如果第二次被包含时,同样会进行判断 此时判断的条件不成立,因为第一次被包含时已经创建了宏变量ABC 所以这样一来,避免了重复包含同一个头文件 ABC宏名称不能和别的头文件中的冲突!所以一般使用当前.h头文件名称命名 */ // #ifndef等同于#if !define,对应的有#ifdef 等同于 #if define #ifndef ABC // ABC一般写成当前头文件的名称,后面的值随便写 #define ABC 11 int sum(int,int); #endif typedef定义类型的别名(一般是全局变量,方便被使用),使用typedef以后,会提高开发效率应用于5个场合基本数据类型指针枚举结构体指向函数的指针应用于基本数据类型
//需要分号 typedef int MyInt; int main(){ //声明别名后,可以这样定义int类型变量 MyInt i = 10; } 应用于指针
//给指针类型起了一个别名String type char* String; int main(){ String = “luoguankun”; } 应用于结构体
//定义了一个结构体类型Student struct Student { int age; }; //给结构体Student起了个别名叫做Mystu typedef struct Student MyStu; //或者像下面这样,在定义结构体类型的时候直接起别名,这样更加精简 typedef struct Student { int age; }MyStu; //如果像上面这样给结构体起了别名,定义结构体变量就变成了下面这样: MyStu s1; MyStu s2; MyStu s3; //还有一种是没有类型名的结构体 //下面的结构体不能使用原本的方式创建结构体变量 //只能通过下面的方式创建结构体变量,无法用struct Student stu = {10};这种方式创建结构体变量, //而前面几种两种创建结构体变量的方式都可以 //而这个只能像下面这样创建: //MyStu stu; typedef struct { int age; }MyStu; 应用于枚举类型
//以下是没有使用typedef定义别名时的枚举使用 enum Sex {Man, Woman}; enum Sex s = Man; //以下是使用typedef定义别名后的使用方法 typedef enum Sex MySex; MySex s = man; //还可以在定义枚举类型的同时定义别名(推荐这样定义) typedef enum Sex {Man, Woman} MySex; MySex s1 = man; 应用与指向函数的指针
//定义一个函数 int sum(int a, int b){ return a+b; } //指向上面函数的指针声明和调用 int (*p)(int, int) = sum; int result = p(10,20); //使用typedef为指向函数的指针定义别名 typedef int (*MyPoint)(int, int); MyPoint p = sum; int result = p(20,20); 简化指向结构体的指针
//简化前 struct Person{ int age; }; struct Person p = {20}; struct Person *p2 = &p; printf("age = %d\n”, p2->age); //简化后 typedef struct Person{ int age; } *PersonPoint; struct Person p = {20}; PersonPoint p2 = &p; printf("age = %d\n", p2->age);
二、static和extern对函数的作用
这两个关键字分别代表内部和外部函数static —— 内部函数,只能被本文件访问,其他文件不能访问,但可以通过外部函数间接访问extern —— 外部函数(默认)在多文件开发的情况下,不同文件中的外部函数不可以重名,内部函数可以同名,但在同一个文件中内外部函数都不能重名定义完整的外部函数需要在函数前加上extern关键字,也可以省略,因为它是默认的定义内部函数需要在函数前面加上static关键字虽然被static关键字修饰的函数不能被外部文件直接调用,但可以间接调用,在外部函数中调用内部函数(条件是要被间接调用的内部函数和外部函数在同一个文件),并且必须在外部函数的上面被声明初学者有什么不懂的可以私信我,需要系统学习资料和系统学习框架图的同学,可关注小编头条号,欢迎留言评论和私信小编。【私信方法】文章上方处点击“作者头像”,进入作者首页,在作者主页上方点击“关注”旁边的“发私信”即可。私信内容:学习帮助。
三、static和extern对变量的作用
全局变量分为两种:外部全局变量——默认,类型关键字前面无需加任何修饰符内部全局变量——被static修饰符修饰默认情况下,所有的全局变量都是外部变量,不同文件中的同名变量,都代表同一个变量内部变量:只能被本文件访问,不能被别的文件访问,不同文件同名的内部变量,互不影响static对变量的作用:定义一个内部变量extern对变量的作用:声明一个外部变量static对函数的作用:定义和声明一个内部函数extern对函数的作用:定义和声明一个外部函数(可以省略)希望小编文章的朋友可以关注、收藏、转发、留言,,也可以私信我(学习帮助),我将给你提供学习上的帮助
最后祝大家阅读愉快!!


还没有评论,来说两句吧...