I have the following macros (follow up to: 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)
The problem is that the mu_format_specifier seems to resolve to a char *
rather than simply substituting "%lu"
into "required: %s != %s, reality: %s == " mu_format_specifier(actual),
which I would like to yield "required: %s != %s, reality: %s == " "%lu"
which C would understand as one literal string.
I can see two horrible work arounds:
make a version of version of mu_assert_equal for each type, and call the right one with a
_Generic
.snprintf the formatting string, though I may run into problems if the formatting string has to be
const
.
Is there a better alternative?
(The problem is that _Generic
actually evaluates an expression, rather than simply substituting source characters - i.e. the "%lu"
becomes it's own literal string, rather than just producing source characters which are unified with "required: %s != %s, reality: %s == "
.)