我试图更好地理解“定义处理”并将asssert.h文件作为一个简单的例子。代码是:
# define assert(EX) (void)((EX) || (__assert (#EX, __FILE__, __LINE__),0))
我对“或”这个词感到困惑。我假设这一行是说,如果表达式为true,则不执行任何操作;如果为false,则调用断言函数。但是预处理器如何处理行,或者在哪里确定assert的定义?为什么选(空)演员?
谢谢你的澄清。
最佳答案
注意,在这种情况下,预处理器不计算任何东西,它只是
用传递的表达式对宏进行文本替换。
假设变量int x = 2;
当您执行assert(x == 3)
时,预处理器将其扩展为
(void)((x == 3) || __assert("x == 3", "test.c", 13),0);
因为
x
是2,x==3
被计算为false,而右侧必须是评估(见Short-Circuit evaluation)。当右边
是evaluted(假设源是
text.c
并且您在第13行执行了该操作)__assert("x == 3", "text.c", 13),0
__assert
将在文本上打印类似x==3失败的内容。c:13。使用逗号运算符所以继续计算下一个表达式并返回该值作为结果
整个表达式的结果(参见comma operator),在本例中为0,因此
((x == 3) || __assert("x == 3", "test.c", 13),0);
是0。
__assert
可能是一个函数或另一个宏,但由于您没有显示了
__assert
的定义,我将其视为一个函数。如果
x
是3,那么x == 3
将被评估为true,而右侧将不是因为如果两边都是真的,并且
左边已经是真的,那么就不需要计算右边
(同样,请参见Short-Circuit evaluation)。
||
用于在编译时关闭编译器,并显示所有警告,编译器可能会警告您不要使用变量。