如何制作宏 return 个字符而不是字符串?
How to make a macro return characters rather than a string?
我有以下宏(跟进:):
#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 == "
.)
我成功了:
#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, _Generic( \
(actual), \
unsigned long: "required: %s != %s, reality: %s == %lu", \
int: "required: %s != %s, reality: %s == %i" \
), \
#actual, #expected, #actual, actual); \
return message; \
} \
} while (0)
解决方案是使整个格式化字符串成为 _Generic
.
的输出 expression
来自测试代码:
mu_assert_equal(bytes_parsed, 1);
我得到输出:
required: bytes_parsed != 1, reality: bytes_parsed == 0
我有以下宏(跟进:
#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 == "
.)
我成功了:
#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, _Generic( \
(actual), \
unsigned long: "required: %s != %s, reality: %s == %lu", \
int: "required: %s != %s, reality: %s == %i" \
), \
#actual, #expected, #actual, actual); \
return message; \
} \
} while (0)
解决方案是使整个格式化字符串成为 _Generic
.
来自测试代码:
mu_assert_equal(bytes_parsed, 1);
我得到输出:
required: bytes_parsed != 1, reality: bytes_parsed == 0