在 C 中编写宏时,如何找到参数的类型和 printf 说明符?

When writing a macro in C, how do I find the type and printf specifier for an argument?

我想用宏扩展 minunit 以使其更有用。

#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 == %lu", \
    #actual, #expected, #actual, actual);                                                 \
    return message;                                                                       \
  }                                                                                       \
} while (0)

调用方式:

mu_assert_equal(bytes_parsed, 1);

但上面的宏仅适用于无符号长值。

如何找到宏参数的类型,更重要的是,它们的 printf 说明符。

你不能,在 C11 之前的 C 中(添加 generics)。

无法计算 C 中表达式的类型,而这正是您需要做的。如果可能的话,那么 printf() 就不会 需要 首先或多或少地使用静态说明符。

如果没有泛型,也许最好的方法是针对不同的类型使用不同的宏:

#define mu_assert_equal(actual, expected, test, fmt) do {                                 \
  if ( test ) {                                                                           \
    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 == " fmt,\
    #actual, #expected, #actual, actual);                                                 \
    return message;                                                                       \
  }                                                                                       \
} while (0)

#define mu_assert_equal_int(actual, expected) \
        mu_assert_equal(actual, expected, actual != expected, "%lu")
#define mu_assert_equal_str(actual, expected) \
        mu_assert_equal(actual, expected, strcmp( actual, expected ), "%s")

并调用为:

mu_assert_equal_str( test_str, "abcde" ) ;
mu_assert_equal_int( test_int, 12345 ) ;

(根据评论进行编辑以通过 "generic" 测试)。