Why is inner_LOAD_ATOM(buffer, ATOM_MAX)
converted to scanf("%" "ATOM_MAX" "s", x)
but the wrapped version isnt? I would expect ATOM_MAX(identifier) to be replaced by 10 before it is "passed" to inner_LOAD_ATOM
or LOAD_LINE
and making the wrapper useless. More elaborated answer why the wrapper is necessary would be very appreciated.
#include <stdio.h>
#define ATOM_MAX 10
#define inner_LOAD_ATOM(x, y) scanf("%" #y "s", x) /* inner part */
#define LOAD_ATOM(x, y) inner_LOAD_ATOM(x, y) /* wrapper of inner_LOAD_ATOM */
int main(void)
{
char buffer[ATOM_MAX] = {0, };
/* wrapped works fine */
LOAD_ATOM(buffer, ATOM_MAX);
/* [Warning] unknown conversion
type character 'A' in format [-Wformat=] */
inner_LOAD_ATOM(buffer, ATOM_MAX);
printf("%s\n", buffer);
return 0;
}
It's important to understand that function-like macros don't work like C functions. There is (almost) no sense of a macro call stack or of forwarding arguments from one macro to another. Instead, macro expansion proceeds iteratively -- macro is replaced with its expansion, then the expansion is rescanned for further macros to expand.
A function-like macro's arguments are completely macro expanded before being inserted into the macro's replacement text, except where they are the operands of the stringification (#
) or token-pasting (##
) operator. Therefore, if you invoke inner_LOAD_ATOM(buffer, ATOM_MAX)
directly, ATOM_MAX
is not expanded before the #
operator is applied.
On the other hand, when you invoke LOAD_ATOM(buffer, ATOM_MAX)
, the ATOM_MAX
macro is expanded before LOAD_ATOM()
is expanded. The inner_LOAD_ATOM()
doesn't factor in at that point -- it's just part of the outer macro's replacement text until LOAD_ATOM()
's expansion is re-scanned for further macro expansions.