预处理指令:
例如:#include<stdio.h>
#include<stdlib.h>
#define MAX 20 .............
因为他们由预处理器解释的,所以称作预处理指令。预处理器读取源代码,然后对其修改,并把修改过的源代码传给编译器,再由编译器编译。在我们的例子中预处理器用库函数stdio.h , stdlib.h的内容替换分别执行第一,二条预处理指令(#include),就像把库函数的内容写入到了源文件了一样。同理,对于标识符MAX也一样,在函数编译阶段,编译器将所有的MAX都替换为20。
宏和标识符: 标识符 #define NAME stuff
宏 #define NAME(参数列表) stuff
宏和标识符最主要的区别是宏有参数,而标识符没有参数,他们共同的特点都是
在编译阶段,只要遇见关键字NAME(NAME(参数列表))编译器就替换成stuff),通常将宏名大写,用以和函数区分。
宏的用法:#define定义了一个机制,宏允许把参数替换到文本中,这种实现我们通常成为宏或宏定义。我们需要注意宏的参数左“(”和宏名之间不能有空格, 例如:#define NAME (5) X 是错误的,因为编译器会理解成标识符,而发生错误。还有就是宏的参数列表中的实际值会替换stuff中对应的值参数,为避免发生一些运算错误,我们需要在stuff中能加括号的地方都加上括号。
#define ADD(x) x+x
int sum=ADD(2)*10;
printf("%d\n",sum);
输出的结果不是40,而是22,这时应为宏实现替换的是 int sum=2+2*10,所以为了避免宏在替换时因为优先级引发的错误,我们在stuff
中
能加括号的地方都加上括号,#define ADD(x) ((2)+(2)) “当参数太多时可以使用“\”(续航符)将参数写在多行)”
"##":这个符号是把位于他两边的字符连成一个标识符,例:
#define ADD_SUM(sum_num,value) sum##sum_num=value
..................
ADD_SUM(5,10)代表的就是sum5=10,需要注意的是使用##链接生成的标识符必须是合法的。
#undef:这个指令用于移除一个宏定义,即一个现存的名字需要被重定义,则首先用#undef将旧定义移除。
命令行定义:允许你在命令行中定义符号,用于启动编译过程。例如:char arr[ARR_SIZT] ARR_SIZE可以再命令行中定义,以便于在不同条件下修改数组的大小。
条件编译:可以选择代码的一部分是被正常编译还是被忽略,
#if connstant-expression(常量表达式,如果为真statement则编译,否则跳过不编译)
statement
#endif
如果我们要编译一段代码,可以如下面所示,当我们编译时将DEBUG设置为一,当我们要忽略时设置为0,这样就可以将代码保留在源文件中
#define DEBUG 1
#if DEBUG
printf(“%s”,*p);
#endif
条件编译还支持#elif,#else的格式,以便于选择不同的代码段编译:
#if connstant-expression
statement
#elif connstant-expression
statement
....................
#else connstant-expression
statement
#endif
可以嵌套使用。
是否被定义:测试一个符号是否被定义,如果定义,则可执行某个操作,比如调用一个函数。
#ifdef symbol
void fun();
#endif