#define在assert.h示例中

时间:2018-03-06 23:25:38

标签: c c-preprocessor

我试图更好地理解#define处理并查看一个asssert.h文件作为一个简单的例子。代码是:

# define assert(EX) (void)((EX) || (__assert (#EX, __FILE__, __LINE__),0))

我对OR表达式感到困惑。我假设这一行说如果表达式为true,则不执行任何操作,如果为false,则调用__assert函数。但是预处理器如何处理该行以及OR在何处确定assert的定义?为什么(虚空)演员?

感谢您的任何澄清。

1 个答案:

答案 0 :(得分:4)

请注意,在这种情况下,预处理器不评估任何内容,它只是 使用传递的表达式对宏进行文本替换。

我们假设你有变量int x = 2;

执行assert(x == 3)时,预处理器会将其扩展为

(void)((x == 3) || __assert("x == 3", "test.c", 13),0);

由于x为2,x==3评估为false,右侧必须为。text.c 评估(见Short-Circuit evaluation)。当右边 进行评估(假设源是__assert("x == 3", "text.c", 13),0 ,你在第13行做了那个)

__assert

((x == 3) || __assert("x == 3", "test.c", 13),0); 将在text.c:13 上打印 x == 3失败的内容。使用逗号运算符 所以继续评估下一个表达式并返回该值作为结果 整个表达式(见comma operator),在本例中为0,所以是

的结果
__assert

为0. __assert可能是一个函数或另一个宏,但是因为你没有 显示了x的定义,我将其视为一种功能。

如果x == 3为3,那么||会评估为真,而右侧则不会 完全评估,因为(void)如果任何一方为真,则评估为真,如果 左侧已经是真的,那么就没有必要评估右侧了 (再看看Short-Circuit evaluation)。

当您使用所有警告进行编译时,{{1}}可以使编译器静音, 编译器可能会警告您没有使用变量。