C语言如何让assert断言失败时输出未展开的自定义宏条件?
解决方案
完全可以通过新增封装宏实现需求,核心是利用C语言预处理器的*字符串化操作符(#)*的执行优先级特性:如果我们在自定义的封装宏里先对传入的条件做字符串化,此时预处理器还未展开条件里的自定义宏,就能保留原始的表达式文本。
封装实现代码
#include <assert.h> // 自定义断言宏 #define MY_ASSERT(cond) do { \ if (!(cond)) { \ __assert_fail(#cond, __FILE__, __LINE__, __func__); \ } \ } while(0) // 你原来的IMPLIES宏 #define IMPLIES(a,b) (!(a) || (b))
原理说明
- 原生
assert()宏的内部逻辑是先把传入的表达式完全展开,再对展开后的结果做字符串化输出,所以你会看到IMPLIES被替换后的逻辑运算内容。 - 自定义的
MY_ASSERT里,字符串化操作#cond会优先执行:预处理器会先把你传入的原始未展开的表达式直接转成字符串,之后才会展开cond用于实际的条件判断,因此__assert_fail输出的错误信息就会是你写的原始内容,比如IMPLIES(d_pos > s_pos, d_pos >= s_pos + count),而非展开后的长表达式。
兼容性说明
__assert_fail是glibc等主流C标准库实现assert()时用到的标准报错函数,绝大多数Linux、Unix环境以及MinGW环境都可以直接使用。如果是特殊编译环境找不到该函数,也可以自己实现报错逻辑,把#cond的字符串内容打印出来之后调用abort()即可,效果完全一致。
内容的提问来源于stack exchange,提问作者U. Windl
相关产品推荐
相关产品推荐

