008-预处理
预处理
1、宏定义
2、条件编译
3、文件包含
注意:
1、所有预处理都是以#开头,并且结尾不用分号.
2、宏名一般用大写字母,以便与变量名区别开来,但用小写也没有语法错误
3、作用域也是从定义到代码块结束
4、定义一个宏时可以引用已经定义的宏名
5、在编译预处理用字符串替换宏名时,不作语法检查,只是简单的字符串替换。只有在编译的时候才对已经展开宏名的源程序进行语法检查
一、宏定义
1、不带参数的宏定义
#define 宏名 字符串
#define COUNT 6
2、带参数的宏定义
#define 宏名(参数列表) 字符串
#define sum(va,vb) ((va)+(vb))
注意:每个参数都要加括号,运算结果也要加括号
若需要提前取消宏定义可用 #undef COUNT实现。
代码示例:
1 //宏名一般用大写字母,以便与变量名区别开来,但用小写也没有语法错误 2 //1、宏定义1,不带参数的宏定义,常用来定义常量 3 #define COUNT 6//后面么有';' 4 5 #include <stdio.h> 6 //1、宏定义2,带参数的宏定义,每个参数都要加括号,运算结果也要加括号 7 #define sum(v1,v2) ((v1)+(v2)) 8 9 10 int main() 11 { 12 //1、宏定义使用 13 int array[COUNT] = {1,2,3,4,5,6}; 14 for (int i = 0; i < COUNT; i++) 15 { 16 printf("%d ",array[i]); 17 } 18 #undef COUNT //提前取消宏定义 19 //带参数的宏 20 printf("\n%d\n",sum(10,20)); 21 printf("%d\n",sum(3,3)*sum(4,4));//这样实际运行效果是3+3*4+4=19,因为宏只是简单的文本替换,所以定义时加()比较好 22 23 //2、条件编译 24 25 26 return 0; 27 }
二、条件编译
满足条件就对代码进行编译,否则不编译。
#if 条件1
.....
#elif 条件
......
#else
.....
#endif//不可缺少
1 #define COUNT 6//后面么有';' 2 //2、条件编译,一般判断宏的值,不能对变量进行操作 3 #if(COUNT == 6) 4 printf("条件编译:%d\n",COUNT); 5 #elif (COUNT == 4) 6 7 #else 8 9 #endif//不可缺少
#if defined()和#if !defined()的使用
#if defined(COUNT)//COUNT是一个宏,如果定义这个宏就执行下面的代码
...code...
#endif
#if !defined(COUNT)//COUNT是一个宏,如果没有定义这个宏就执行下面的代码
...code...
#endif
代码:
1 //#if defined()和#if !defined()的用法 2 #if defined (COUNT)//如果定义宏就编译下面代码,否则不编译 3 printf("defined:%d\n",COUNT); 4 #endif 5 6 #if !defined (COUNT1)//如果定义宏就编译下面代码,否则不编译 7 printf("! defined\n"); 8 #endif
#ifdef和#ifndef的使用
#ifdef COUNT//COUNT是一个宏,如果定义这个宏就编译下面的代码
...code...
#endif
#ifndef COUNT//COUNT是一个宏,如果没有定义这个宏就编译下面的代码
...code...
#endif
代码:
1 //#ifdef和#ifndef的使用 2 #ifdef COUNT//如果定义宏就编译下面代码,否则不编译 3 printf("ifdef:%d\n",COUNT); 4 #endif 5 6 #ifndef COUNT1//如果定义宏就编译下面代码,否则不编译 7 printf("ifndef\n"); 8 #endif
三、文件包含
#include
#include <>//系统头文件
#include ""//自定义的头文件
文件包含可能会重复包含同一个文件,这是可以再要包含的文件中添加一个宏定义,用于消除重复包含。
格式如下
#ifndef A_H
#def A_H
..........
#endif
这样即使多次#include同一个头文件也不会产生文件的重复性包含
四、typedef
typedef的用法:
1、为各种数据类型定义一个新名字(别名)
2、typedef与指针
3、typedef与结构体
4、typedef与指向结构体的指针
5、typedef与枚举类型
6、typedef与指向函数的指针
7、typedef与#define
代码示例
1 #include <stdio.h> 2 /* 3 typedef的用法: 4 1、为各种数据类型定义一个新名字(别名) 5 2、typedef与指针 6 3、typedef与结构体 7 4、typedef与指向结构体的指针 8 5、typedef与枚举类型 9 6、typedef与指向函数的指针 10 7、typedef与#define 11 */ 12 13 //3、typedef与结构体 14 struct Point 15 { 16 int x; 17 int y; 18 }; 19 20 //也可以直接在定义时使用typedef 21 typedef struct Point1{}point1; 22 23 //起别名,下面可以直接使用,而不用每次都写struct 24 typedef struct Point MyPoint; 25 26 //自定义结构体指针,起别名 27 typedef MyPoint *pp; 28 29 30 31 // 5、typedef与枚举类型 32 enum Sex{male,female,notSure}; 33 typedef enum Sex Sex;//起别名 34 35 // 6、typedef与指向函数的指针 36 int Sum(int a,int b) 37 { 38 int c = a + b; 39 printf("%d + %d = %d\n",a,b,c); 40 return c; 41 } 42 43 44 45 int main() 46 { 47 //1、为各种数据类型定义一个新名字(别名) 48 typedef int Integer; 49 50 Integer i = 10; 51 printf("%d\n",i); 52 53 //1、typedef与指针 54 typedef char *String; 55 String name = "this is a typedef struct"; 56 printf("%s\n",name); 57 58 //3、typedef与结构体 59 MyPoint p1; 60 p1.x = 1; 61 p1.y = 2; 62 printf("%d,%d\n",p1.x,p1.y); 63 64 //4、typedef与指向结构体的指针 65 pp p = &p1; 66 p->x = 10; 67 p->y = 20; 68 printf("%d,%d\n",p->x,p->y); 69 70 // 5、typedef与枚举类型 71 Sex s1 = male;//使用别名进行变量声明,不用带关键字enum 72 printf("%d\n",s1); 73 74 // 6、typedef与指向函数的指针 75 //普通函数指针使用方式 76 int (*pSum)(int ,int );//普通函数指针定义 77 pSum = ∑ 78 (*pSum)(19,20); 79 80 typedef int (*pS)(int ,int );//使用typedef给函数指针起别名 81 pS ps = ∑//这个使用方式和上面有些差别 82 (*ps)(19,20); 83 84 //7、typedef与#define 85 #define String1 char* 86 typedef char* String2; 87 String1 str1,str2;//宏替换 char* str1,str2;//str2只是一个字符变量,不是指针变量 88 String2 str3,str4; //但是这个是这样,char *str3;char * str4; 89 90 return 0; 91 }
static和extern
static和extern与函数
关于函数:
外部函数:如果在当前文件中定义的函数允许其他文件访问、调用,就称为外部函数。C语言规定,不允许有同名的外部函数。
内部函数:如果在当前文件中定义的函数不允许其他文件访问、调用,只能在内部使用,就称为内部函数。C语言规定不同的源文件可以有同名的内部函数,并且互不干扰。
one.h
//one.h #include "one.c" extern void one(); void anotherOne();
one.c
1 //one.c 2 3 4 #include <stdio.h> 5 6 extern void one()//默认就是extern函数,不写效果一样。外部函数 7 { 8 printf("one is called!\n"); 9 } 10 static void anotherOne()//只能在one.c中使用。内部函数 11 { 12 printf("anotherOne is called!\n"); 13 }
主函数
1 #include <stdio.h> 2 //#include "one.h" 3 /* 4 extern与static 5 1、extern与函数==外部函数 6 2、static与函数==内部函数 7 */ 8 9 //1、extern与函数 10 //#include "one.c"//这样引用会提示重复定义one 11 //extern void one();//可以这样进行外部声明,但是extern可以省略,所以可以直接写成 void one(); 12 //实际情况下一般把声明写道头文件里,直接包含头文件,可以直接使用里面的函数 13 // 2、static与函数 14 //只能再定义的文件内使用,无法被外部文件引用 15 16 void anotherOne();//引用声明 17 18 int main() 19 { 20 one(); 21 anotherOne(); 22 return 0; 23 }
static和extern与全局变量
1、全局变量可以重复定义,只要变量名一样,指的都是一个变量,在多个文件中也是如此。
int b1;
int b1;
int b1;
2、如果变量的定义在下面,但是又想提前使用就需extern声明
extern int a;
3、在函数内部也可以通过extern int a;使用全局变量a,以区别同名的局部变量
4、全局静态变量,只能在本文件内部使用
1 #include <stdio.h> 2 //3、全局变量和static 3 static int b;//全局静态变量,只能在本文件内部使用 4 //全局变量可以重复定义,只要变量名一样,指的都是一个变量,在多个文件中也是如此。 5 int b1; 6 int b1; 7 int b1; 8 // 4、全局变量和extern 9 extern int a;//a的定义在下面或者在其他文件里,如果想提前使用就需extern声明 10 11 int main() 12 { 13 { 14 //在函数内部访问同名全局变量1 15 extern int b1; 16 b1 = 12; 17 } 18 //在函数内部访问同名全局变量2 19 int *p = &b1; 20 21 int b1; 22 b1 = 20; 23 24 25 return 0; 26 } 27 28 int a;