我正在阅读“没有错误!”作者:David Thielen,第 3 章讨论了一种确定给定代码路径是否已被命中的方法。它建议使用一个宏来检查参数,如果参数为真,则执行生成特定中断(0x3)的汇编指令以创建调试器断点。如果宏的参数为 false,则它不会执行任何操作。
宏看起来像这样:
#ifdef DEBUG
#define Trap(t) ( (t) ? __asm__("int $0x3") : )
#endif
但是,此代码会导致 gcc 编译错误:
int_test.c:16:35: error: expected expression before ‘__asm__’
我是从here学到的因为 gcc 的 asm 是 block 语句而不是表达式,所以我必须使用 statement expressions为了以这种方式使用asm。所以,现在变成了:
#define Trap(t) ( (t) ? ({ __asm__("int $0x3"); }) : )
编译器仍然提示:
int_test.c:16:64: error: expected expression before ‘)’ token
好吧,现在我必须这样做?
#define Trap(t) ( (t) ? ({ __asm__("int $0x3"); }) : ({ ; }) )
这看起来真的很愚蠢。如果 t
为 false,我不能让预处理器插入任何内容而不使用这种烦人的语法吗?
注意:为了简单起见,我省略了一些其他类似的宏,并且我已经调整了书中的语法以适用于 gcc(例如用 asm 替换本书的 _asm 以及使用 AT&T语法和围绕“”中的汇编)
最佳答案
您从本书中得到的建议本质上是创建您自己的 assert()
功能。
在大多数系统上,您应该只使用 assert.h
中提供的 assert()
宏。如果触发断言并且您在调试器下运行,则断言将触发断点(同样 - 在大多数系统上)。
如果由于某种原因您无法使用标准 assert.h
功能(例如,可能是某种不提供该功能的简单嵌入式系统工具链),您可以这样做像下面这样:
#ifdef DEBUG_MODE
void DoAssert(void);
#define ASSERT(expr) ((expr) ? (void) 0 : DoAssert())
#else
#define ASSERT(expr) ((void) 0)
#endif
并将您需要捕获的任何内容放入 DoAssert()
函数中的调试器中 - 在您的情况下,这将是 int 3
的内联程序集。
关于c - 如何使用三元运算符创建 #define 宏,其中一个操作数不执行任何操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20577065/