【发布时间】:2015-01-16 18:34:05
【问题描述】:
我有以下宏(跟进:When writing a macro in C, how do I find the type and printf specifier for an argument?):
#define mu_format_specifier(expression) _Generic((expression), unsigned long: "%lu", int: "%i")
#define mu_assert_equal(actual, expected) do { \
if (actual != expected) { \
char *message = malloc(MAX_ERROR_MESSAGE_LENGTH); \
if (message == NULL) { printf("malloc failed"); exit(1); } \
snprintf(message, MAX_ERROR_MESSAGE_LENGTH, \
"required: %s != %s, reality: %s == " mu_format_specifier(actual), \
#actual, #expected, #actual, actual); \
return message; \
} \
} while (0)
问题在于 mu_format_specifier 似乎 解析为 char * 而不是简单地将 "%lu" 替换为 "required: %s != %s, reality: %s == " mu_format_specifier(actual), 我想产生 "required: %s != %s, reality: %s == " "%lu" 将 C 理解为一个文字字符串。
我可以看到两种可怕的变通方法:
为每种类型创建一个 mu_assert_equal 版本,并使用
_Generic调用正确的版本。snprintf 格式化字符串,但如果格式化字符串必须是
const,我可能会遇到问题。
有没有更好的选择?
(问题在于_Generic 实际上是对一个表达式求值,而不是简单地替换源字符——即"%lu" 成为它自己的文字字符串,而不是仅仅产生与"required: %s != %s, reality: %s == " 统一的源字符。)
【问题讨论】:
-
预处理阶段的输出是什么?
-
@SergeBallesta 这就是我修复它的方法 - 我保存了预处理器输出,然后阅读了错误消息,这要好得多。这让我看到
_Generic的输出是一个表达式,而不是一系列源代码字节。我错误地认为 _Generic 是某种形式的简单宏扩展。