代码编译包含4个阶段:预编译、编译、汇编、链接
详细过程
预处理详解
预定义符号
__FILE__ //进行编译的源文件
__LINE__ //文件当前行
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果文件遵循ANSI C 其值为1, 否则未定义
实例1
int main()
{
int i = 0;
for (i = 0; i < 3; i++)
{
printf("file:%s line=%d date:%s time:%s i=%d\n", __FILE__, __LINE__, __DATE__, __TIME__, i);
}
}
输出
file:E:\C_Learing\C_Learning\C_Learning\test.c line=2009 date:Aug 30 2024 time:10:59:13 i=0
file:E:\C_Learing\C_Learning\C_Learning\test.c line=2009 date:Aug 30 2024 time:10:59:13 i=1
file:E:\C_Learing\C_Learning\C_Learning\test.c line=2009 date:Aug 30 2024 time:10:59:13 i=2
实例2
int main()
{
FILE* pf = fopen("test.txt", "w");
if (NULL == pf)
{
perror("fopen");
return EXIT_FAILURE;
}
int i = 0;
for (i = 0; i < 3; i++)
{
fprintf(pf, "file:%s line=%d date:%s time:%s i=%d\n", __FILE__, __LINE__, __DATE__, __TIME__, i);
}
fclose(pf);
pf = NULL;
}
打印的内容重定向到文件test.txt中,如下图:
所以此实例,可以用在日志文件的操作。
define
difine 定义宏
#define 机制包括了一个机制,允许把参数替换到文本中,这种实现通常称为宏(macro)
下面是宏的申明方式:
#define name(parament-list) stuff
其中的parament-list是一个由逗号隔开的符号表,它们可能出现在stuff中
注意:
参数列表的左括号必须与name紧邻。
如果两者之间有任何的空白存在,参数列表就会被解释为stuff的一部分
实例1
#define SQUARE(x) x*x
int main()
{
int a = SQUARE(3);
printf("%d\n", a); //9
a = SQUARE(2 + 3); //替换为:2+3*2+3 = 11
printf("%d\n", a);
return 0;
}
输出
9
11
由以上结果可知,宏的参数是直接替换的,而不会先计算(2+3 = 5),所以在定义宏的时候要加括号(), 如下实例:
实例2
#define SQUARE(x) (x)*(x)
int main()
{
int a = SQUARE(3);
printf("%d\n", a); //9
a = SQUARE(2 + 3); //替换为:(2+3)*(2+3) = 25
printf("%d\n", a);
return 0;
}
输出
9
25
实例3
#define DOUBLE(X) (X)+(X) //参数要加上()
int main()
{
int a = DOUBLE(3);
printf("%d\n", a);
a = 10 * DOUBLE(3); //替换为:10*(3)+(3) = 33
printf("%d\n", a);
return 0;
}
输出
6
33
而第二个打印结果,我们期待的应该是60,那如何获得正确结果,如下实例讲解
实例4
#define DOUBLE(X) ((X)+(X)) //最外面也要加上()
int main()
{
int a = DOUBLE(3);
printf("%d\n", a);
a = 10 * DOUBLE(3); //替换为:10*((3)+(3))=60
printf("%d\n", a);
return 0;
}
输出
6
60
由以上所有实例可知,在宏定义的时候,要把参数以及最外层都要加上()