前言:
前几次讲解了一个程序从写出的C语言代码到预编译——>编译——>转汇编——>链接——>可执行程序。
其中翻译环境我们基本上了解了,大概清楚其中的原理,接下来探究一下预编译阶段的过程。
预定义符号:
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义
这些符号在进行与编译阶段就会被替换成相应的信息,在运行时进行打印。
例如:
#include<stdio.h>
#define M 100
int main()
{
//预定义符号
printf("%s\n", __FILE__);
printf("%d\n", __LINE__);
printf("%s\n", __DATE__);
printf("%s\n", __TIME__);
return 0;
}
在VS2019\2022中的编译器没有严格遵循ANSI C!!
#define定义的标识符
#include<stdio.h>
#define M 100 //给M赋值为100
#define AD advance_int//给advance_int重新取一个简短的名字AD
#define CASE break;case //在写case语句的时候自动把 break写上。
int main()
{
int a = 0;
a = M;
int AD = M;
printf("%d\n", a);
printf("%d\n", AD);
int i = 0;
scanf("%d", &i);
switch (i)
{
case 1:
CASE 2 :
printf("%d\n", i);
CASE 3:
printf("%d\n", i);
CASE 4:
printf("%d\n", i);
}
return 0;
}
参与编译阶段#define定义的标识符被自动替换,也就变成如下:
#include<stdio.h>
int main()
{
int a = 0;
a = 100;
int advance_int = 100;
printf("%d\n", a);
printf("%d\n", advance_int);
int i = 0;
scanf("%d", &i);
switch (i)
{
case 1:
break;case 2:
printf("%d\n", i);
break;case 3:
printf("%d\n", i);
break;case 4:
printf("%d\n", i);
}
return 0;
}
#define定义的宏
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。
例如:
#define add(x,y) ((x)+(y))//定义一个有参数的函数
#define mul(x,y) ((x)*(y))
int main()
{
int a = 10;
int b = 20;
int c = add(a, b);
int d = mul(a, b);
printf("%d\n", c);
printf("%d\n", d);
return 0;
}
#define 替换规则
在程序中扩展#define定义符号和宏时,需要涉及几个步骤。
1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上 述处理过程。
注意:
1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。 2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。
#define中##的作用
#define add(x,y) ((x)+(y))//定义一个有参数的函数
#define mul(x,y) ((x)*(y))
#define add2(x,y) x##y+=y//意思是给xy +10
int main()
{
int a = 10;
int b = 20;
int c = add(a, b);
int d = mul(a, b);
int e = add2(a, b);//出现编译错误
printf("%d\n", c);
printf("%d\n", d);
printf("%d\n", e);
return 0;
}
作用:
##可以把位于它两边的符号合成一个符号。
它允许宏定义从分离的文本片段创建标识符。
#undef
这条指令用于移除一个宏定义。
例如:
没有使用#undef之前:
#include<stdio.h>
#define M 100
int main()
{
int a = 0;
a = M;
printf("%d\n", a);
return 0;
}
使用#undef之后
#include<stdio.h>
#define M 100
#undef M
int main()
{
int a = 0;
a = M;
printf("%d\n", a);
return 0;
}