一、#define定义标识符

1.基本使用方法

常见方法

#define M 100
int main()
{
	printf("%d\n", M);
	return 0;
}

少见但仍正确的用法

#define R register
int main()
{
	R int a = 100;
	//R相当于关键字register
	return 0;
}

当然#define还有其它用法(难以置信但合理的),如:

#define do_forever for(;;)    
#define CASE break;case

其它可自行探索……

2.#define中的换行

image.png
错误的:
image.png
正确的:
image.png
原因:我们所使用的回车键也是一个字符,加上\将回车转义,使编译器认为这几行仍是一行,避免错误。

3.#define后的;

相信大家都了解#define定义的标识符后不应加;
现在来验证是否应加;(环境:VScode)
相关安装和操作及解释:程序的运行过程
image.png
输入指令gcc test.c -E -o test.i生成test.i文件,该文件是将源代码经过预编译形成的文件。此时可以看到编译器将M替换成了100;
可以说明#define定义的标识符会被替换成其定义的内容。因此#define后的;可以加也可以不加。

二、 #define定义宏

#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。

1.基本使用方法

image.png

宏的申明方式: #define name( parament-list ) stuff
其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。

注意: 参数列表的左括号必须与name紧邻。 如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分
此时输入指令生成test.i文件,test.i为经过预编译的文件,结果如下:
image.png
可以看到与#define定义标识符一样的操作。(该操作方便理解下文的内容)

2.#define定义的宏建议加( )

如:image.png
为什么应该加上( )呢?我们先讨论内部( )
相信大家都遇到过这个问题:明明输入的x的值为3+2,结果却是11而不是25
image.png
寻找原因,生成test.i文件,观察经过预编译后生成的文件:
image.png
可以看出编译器并不会先计算3+2再进行运算,而是直接进行替换,因此需要加上( )来保证结果的正确性。
接下来讨论外部( )
举个例子来直观感受:
image.png
生成test.i文件后来观察原因:
image.png
不用我解释,大家也能明白原因。因此在加内部( )时也需加上外部( )

三、#define替换规则

在程序中扩展#define定义符号和宏时,需要涉及几个步骤。

  1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
  2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
  3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。

注意:

  1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
  2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

四、带副作用的宏参数

当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。
例如

x+1;//不带副作用
x++;//带有副作用

举例:大家可以计算一下打印的a、b、c的值是什么
image.png
转化为test.i文件后为:
image.png
注意:image.png
那么如果MAX是函数呢?
image.png
与宏MAX不同,函数MAX的结果是4、5、4。这是为什么呢?原因如下:与宏不同,函数传参时传的是计算好的值,而非整个替换进去。
因此可以看出该宏参数是有副作用的。

五、#undef 移除宏定义

这条指令用于移除一个宏定义
举例:
image.png

六、#与##

1.#的作用

#用于将参数插入字符串中。
举例:用#define编写一个打印函数:
image.png
其中打印结果为:
image.png
现在我们希望x替换成a、b、c
那么就需要预处理指令#了,具体做法如下:
image.png
注意:#应用于两个字符串之间。
若不使用#则结果如下:
image.png

2.##的作用

##可以把位于它两边的符号合成一个符号。 它允许宏定义从分离的文本片段创建标识符。
image.png

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐