1.预处理
编译可以分解成:预处理(有些书也叫预编译)、编译、汇编三个过程。我们在这篇文章中主要讨论预处理相关内容。
在预处理阶段,源文件和头文件会被处理成为.i为后缀的文件。预处理阶段主要处理那些源文件中#开始的预编译指令。比如:#include,#define,处理的规则如下:
(1)所有的 #define 删除,并展开所有的宏定义。
(2)处理所有的条件编译指令,如: #if 、 #ifdef 、 #elif 、 #else 、 #endif 。
(3)处理#include预编译指令,将包含的头文件的内容插入到该预编译指令的位置。这个过程是递归进行的,也就是说被包含的头文件也可能包含其他文件。
(4)删除所有的注释
(5)添加行号和文件名标识,方便后续编译器生成调试信息等。
(6)或保留所有的#pragma的编译器指令,编译器后续会使用。
(6)经过预处理后的.i文件中不再包含宏定义,因为宏已经被展开。并且包含的头文件都被插入到.i文件 中。所以当我们无法知道宏定义或者头文件是否包含正确的时候,可以查看预处理后的.i文件来确认。
2.预定义符号
预定义符号是在编程语言中事先定义好的具有特定含义和用途的符号,可以直接使用,预定义符号也是在预处理期间处理的。
//__是两个下划线
__FILE__ //进⾏编译的源⽂件
__LINE__ //⽂件当前的⾏号
__DATE__ //⽂件被编译的⽇期
__TIME__ //⽂件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义
int main()
{
printf("file:%s line:%d date:%s ", __FILE__, __LINE__ , __DATE__);
return 0;
}
2.#define
“#define”是 C/C++ 语言中的预处理器指令,用于定义常量和宏。
通过“#define”,可以给一个标识符指定一个值或者一段代码片段。
例如,“#define PI 3.14159” 定义了一个名为“PI”的常量,其值为 3.14159 。
再比如,“#define SQUARE(x) ((x) * (x)) ” 定义了一个名为“SQUARE”的宏,用于计算一个数的平方。
使用“#define”可以增加代码的可读性和可维护性,但如果使用不当,可能会导致一些意外的结果,比如参数的副作用等。
2.1#define定义常量
#define max 1000
#define min 10;
int main()
{
int x = max;
int n = min //min被替换为10;
printf("%d ", x);
printf("%d ", n);
return 0;
}
2.2#define定义宏
#define 机制包括了⼀个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏 (definemacro)。