我试图更好地理解“定义处理”并将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)。
||用于在编译时关闭编译器,并显示所有警告,
编译器可能会警告您不要使用变量。

09-04 01:52