目录
预定义符号:
使用:
结果:
预编译前后对比:
#define定义常量:
基本语法:
举例1:
结果:
预编译前后对比:
举例2:
预编译前后对比:
注意事项:
#define定义宏:
下⾯是宏的申明⽅式:
举例:
使用:
预编译前后对比:
结果:
注意事项:
1.参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
举例:
正确的:
错误的:
2.不够严谨的写法导致的失误:
举例:
结果:
使用预编译进行查看替换的情况:
所以严谨的写法应该是:
带有副作用的宏:
举例:
当我们使用a++和b++这种带有永久性的效果时:
预编译前后对比:编辑
结果:
分析:
宏的替换规则:
预定义符号:
C语⾔设置了⼀些预定义符号,可以直接使⽤,预定义符号也是在预处理期间处理的。
__FILE__ //进⾏编译的源⽂件
__LINE__ //⽂件当前的⾏号
__DATE__ //⽂件被编译的⽇期
__TIME__ //⽂件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义
使用:
int main()
{
printf("%s\n", __FILE__);
printf("%d\n", __LINE__);
printf("%s\n", __DATE__ ;
printf("%s\n", __TIME__);
}
结果:
预编译前后对比:
#define定义常量:
基本语法:
#define name stuff
举例1:
int main()
{
int a = Mprintf("%d\n",M);
printf("%s\n",STR);
return 0 :
}
结果:
预编译前后对比:
举例2:
#define forever for( ; ; )
int main()
{
int a = M;
printf("%d\n",M);printf("%s\n",STR);
forever;
return 0;
}
结果是无限循环
预编译前后对比:
注意事项:
在define定义标识符的时候,不要在最后加上 ;
#define定义宏:
#define 机制包括了⼀个规定,允许把参数替换到⽂本中,这种实现通常称为宏(macro)或定义宏 (define macro)。
下⾯是宏的申明⽅式:
#define name( parament-list ) stuff
举例:
#define SOAURE(X) X*X
使用:
#define SOAURE(X) X*X
int main()
{
int a = 5;
printf("%d\n",SQUARE(a));
return 0;
}
预编译前后对比:
结果:
注意事项:
1.参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
举例:
正确的:
#define SQUARE(X) X*X
错误的:
#define SQUARE (X) X*X
错误在于SQUARE举例(x)之间有一个空格,正常来说是不因该又间隔的,这二者应该紧贴在一起,也就是换在原型上来说,name应该和 ( parament-list )紧贴着!
2.不够严谨的写法导致的失误:
举例:
#define SOAURE(X) X*X
int main()
{
int a = 5;
printf("%d\n",SQUARE(a+2));
return 0;
}
按照我们的想法因,再进行#define替换后,应该是(a+2)*(a+2),因为a=5,所以最后的结果因该是7*7=49,但是结果并不是如此。
结果:
使用预编译进行查看替换的情况:
并不是我们想象中的 (a+2)*(a+2),而是a+2*a+2,也就是5+2*5+2=5+10+2=17
所以严谨的写法应该是:
#define SQUARE (X) ((X)*(X))
以此避免因为不严谨而带来的错误。
带有副作用的宏:
当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能出现危险导致不可预测的后果。
副作用就是表达式求值的时候出现的永久性效果。
举例:
#define MAX(a, b) ((a)>(b)?(a):(b))
当我们使用a++和b++这种带有永久性的效果时:
int main()
{
int a = 15;
int b = 9;
int m = MAX(a++, b++);
printf("%d\n",m);
printf("a=%d b=%d\n",a,,b);
return 0;
}
预编译前后对比:
结果:
分析:
通过宏的替换,将 int m = MAX(a++, b++);替换为了int m = ((a++)>(b++)?(a++):(b++));
也正是因为替换,导致了++的不确定性。
- 1.因为a=15,再(a++)>(b++)中进行了使用,使用完后 a和b都因为++加上了1
- 2.因为再(a++)>(b++)中a比b大,所以执行?(a++):(b++));因为是a大,所以只执行(a++),所以最后答案输出给m的是16,但是输出完后,进行++执行,所以a又继续+1,得到17
宏的替换规则:
通过上诉我们得知了,宏是先把对应的内容替换掉,再进行运算。
而在程序中扩展#define定义符号和宏时,需要涉及⼏个步骤。
- 在调⽤宏时,⾸先对参数进⾏检查,看看是否包含任何由#define定义的符号。如果是,它们⾸先 被替换。
- 替换⽂本随后被插⼊到程序中原来⽂本的位置。对于宏,参数名被他们的值所替换。
- 最后,再次对结果⽂件进⾏扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上 述处理过程。