从source code到可执行程序,一般经历一下步骤:
C源码 -》编译预处理 -》编译 -》连接 -》可执行程序
本文只讲述编译预处理的故事,编译预处理有三大作用:
1、宏定义
2、文件包含
3、条件编译
1、宏定义
(1)不带参数的宏定义
define PI 3.1415926
宏定义是在编译之前进行处理的,宏定义只是作简单的替换,不做语法检查。宏定义与变量不同,不能被赋值,不分配内存空间,只作字符替换。
#define命令出现在函数的外面,宏名的有效范围是从定义到本源文件结束,在需要终止有效范围时,可以用#undef,例如
(2)带参数的宏定义
•在此种情况下,多使用括号,以免出现错误.
有 #define S(r) r*r
语句 area=S(a+b); 替换为area=a+b*a+b
正确为#define S(r) (r)*(r)
有 #define S(r) r*r
语句 area=S(a+b); 替换为area=a+b*a+b
正确为#define S(r) (r)*(r)
•替换为area=(a+b)*(a+b)
函数调用是在程序运行时处理的,分配临时的内存单元,有参数的传递过程和返回值;而带参数的宏是在编译时进行的,在展开时并不分配内存单元,无值传递和返回值.
函数调用占用运行时间;而宏替换占用编译时间
2、文件包含
“文件包含”指一个源文件可以将另一个源文件的全部内容包含进来,即将另外的文件包含到本文件之中.
3、条件编译
对其中的一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件.
•(1) #ifdef 标识符
• 程序段1
• #else
• 程序段2
• #endif
•(2) #ifdef 标识符
• 程序段1
• #endif
例子:
当标识符已被定义时(一般用#define命令定义),则对程序段1编译,否则编译程序段2.
Eg: #define COMPUTER_A
#ifdef COMPUTER_A
#define INTEGER _SIZE 16
#else
#define INTEGER _SIZE 32
#endif
以上例子起到开关控制的作用.
(3)
#ifndef 标识符
程序段1
#else
程序段2
#endif
例如:
作用:若标识符未被定义编译程序段1,否则编译程序段2.
Eg: #ifndef RUN
printf(“x=%d,y=%d”,x,y);
#endif
如果未对RUN定义,则输出x,y的值
(4)
#if 表达式
程序段1
#else
程序段2
#endif
例子:当指定的表达式为真时,编译程序段1,否则编译程序段2.
•#define LETTER 1
• main( )
• {
char str[ ]=“C Langue”,c;
int i=0;
• while((c=str[i])!=’\0’)
{
i++;
• #if LETTER
• if(c>=’a’&&c<=’z’)
c=c-32;
• #else
if(c>=’A’&&c<=’Z’)
• c=c+32;
• #endif
printf(“%c”,c);
}
}