#define 在 assert.h 例子中

#define in assert.h example

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

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

我对 OR 表达式感到困惑。我假设这一行是说如果表达式为真,则什么都不做,如果为假,则调用 __assert 函数。但是预处理器如何处理该行以及OR在哪里确定断言的定义?为什么 (void) 强制转换?

感谢您的澄清。

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

假设您有变量 int x = 2;

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

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

因为 x 是 2,所以 x==3 被评估为 false 并且右边必须是 评估(参见 Short-Circuit evaluation)。当右侧 被评估(假设来源是 text.c 而你在第 13 行做了)

__assert("x == 3", "text.c", 13),0

__assert 会打印类似 x==3 failed on text.c:13 的内容。使用逗号运算符 所以继续评估下一个表达式和 return 该值作为结果 整个表达式的(参见 comma operator),在本例中为 0,因此

的结果
((x == 3) || __assert("x == 3", "test.c", 13),0);

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

但是,如果 x 为 3,则 x == 3 的计算结果为真,而右侧则不会 完全评估,因为 || 如果任何一方为真,则评估为真,如果 左侧已经为真,则无需评估右侧 (再次参见 Short-Circuit evaluation)。

(void) 是为了让编译器在编译时带有所有警告时静音, 编译器可能会警告您未使用的变量。