【问题标题】:#define in assert.h example#define 在 assert.h 示例中
【发布时间】:2018-03-06 23:25:37
【问题描述】:

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

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

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

感谢您的澄清。

【问题讨论】:

  • OR 是短路评估的一个例子。 en.wikipedia.org/wiki/Short-circuit_evaluation
  • "但是预处理器如何处理该行以及 OR 在哪里确定断言的定义?" 我不知道你在这里问什么。
  • EX 是被断言的表达式。预处理器完全按照(希望)认为的那样做:使用EX 将替换扩展到您的代码中。如果您像预处理器一样思考并自己尝试了一些替换,假设您了解 stringizing 的工作原理,它可能会更有意义。
  • 您应该创建一个小测试文件,并查看预处理器的输出。使用 gcc 或 clang,-E 选项会显示预处理器输出。

标签: c c-preprocessor


【解决方案1】:

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

假设你有变量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 的内容。使用逗号运算符 所以继续评估下一个表达式并将该值作为结果返回 整个表达式的值(参见comma operator),在本例中为 0,因此结果为

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

为 0。__assert 可能是一个函数或另一个宏,但既然你没有 显示了__assert的定义,我把它当作一个函数。

如果 x 是 3,那么 x == 3 将评估为真,而右侧不会 完全评估,因为|| 如果任一方为真,则评估为真,如果 左边已经是真的,那么右边就不用评价了 (再次,请参阅Short-Circuit evaluation)。

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

【讨论】:

  • 谢谢,太好了。对不起,这个问题的口齿不清。对我来说,困难在于考虑预处理器替换与代码执行。但是您的回答非常有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多