宏将以前的宏标识符字符串化而不是替换它
Macro stringifies a previous macros identifier instead of its replacement
为什么 inner_LOAD_ATOM(buffer, ATOM_MAX)
转换为 scanf("%" "ATOM_MAX" "s", x)
而包装版本却没有?我希望 ATOM_MAX(identifier) 在 "passed" 到 inner_LOAD_ATOM
或 LOAD_LINE
之前被 10 替换并使包装器无用。非常感谢为什么需要包装器的更详细的答案。
#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;
}
因为在第一次传递时 #y
将被 #ATOM_MAX
替换并被字符串化。所以它不会在第二次通过时得到扩展。让我们手动 运行 它:
第一关:
int main(void)
{
char buffer[10] = {0, };
/* wrapped works fine */
inner_LOAD_ATOM(buffer, 10); // <-- Note - here it ATOM_MAX was expanded in the first pass
/* [Warning] unknown conversion
type character 'A' in format [-Wformat=] */
scanf("%" "ATOM_MAX" "s", buffer);
printf("%s\n", buffer);
return 0;
}
第二遍:
int main(void)
{
char buffer[10] = {0, };
/* wrapped works fine */
scanf("%" "10" "s", buffer);
/* [Warning] unknown conversion
type character 'A' in format [-Wformat=] */
scanf("%" "ATOM_MAX" "s", buffer); // <----- Not expanded as is interpreted as string
printf("%s\n", buffer);
return 0;
}
了解 function-like 宏不像 C 函数那样工作很重要。 (几乎)没有宏调用堆栈或将参数从一个宏转发到另一个宏的感觉。相反,宏扩展迭代地进行——宏被它的扩展替换,然后重新扫描扩展以进一步扩展宏。
一个 function-like 宏的参数在被插入到宏的替换文本之前完全被宏展开, 除了 它们是字符串化的操作数(#
) 或 token-pasting (##
) 运算符。因此,如果您直接调用 inner_LOAD_ATOM(buffer, ATOM_MAX)
,则在应用 #
运算符之前不会展开 ATOM_MAX
。
另一方面,当您调用 LOAD_ATOM(buffer, ATOM_MAX)
时,ATOM_MAX
宏会先于 LOAD_ATOM()
展开。 inner_LOAD_ATOM()
在那一点上没有考虑——它只是外部宏替换文本的一部分,直到 LOAD_ATOM()
的扩展为 re-scanned 以进行进一步的宏扩展。
为什么 inner_LOAD_ATOM(buffer, ATOM_MAX)
转换为 scanf("%" "ATOM_MAX" "s", x)
而包装版本却没有?我希望 ATOM_MAX(identifier) 在 "passed" 到 inner_LOAD_ATOM
或 LOAD_LINE
之前被 10 替换并使包装器无用。非常感谢为什么需要包装器的更详细的答案。
#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;
}
因为在第一次传递时 #y
将被 #ATOM_MAX
替换并被字符串化。所以它不会在第二次通过时得到扩展。让我们手动 运行 它:
第一关:
int main(void)
{
char buffer[10] = {0, };
/* wrapped works fine */
inner_LOAD_ATOM(buffer, 10); // <-- Note - here it ATOM_MAX was expanded in the first pass
/* [Warning] unknown conversion
type character 'A' in format [-Wformat=] */
scanf("%" "ATOM_MAX" "s", buffer);
printf("%s\n", buffer);
return 0;
}
第二遍:
int main(void)
{
char buffer[10] = {0, };
/* wrapped works fine */
scanf("%" "10" "s", buffer);
/* [Warning] unknown conversion
type character 'A' in format [-Wformat=] */
scanf("%" "ATOM_MAX" "s", buffer); // <----- Not expanded as is interpreted as string
printf("%s\n", buffer);
return 0;
}
了解 function-like 宏不像 C 函数那样工作很重要。 (几乎)没有宏调用堆栈或将参数从一个宏转发到另一个宏的感觉。相反,宏扩展迭代地进行——宏被它的扩展替换,然后重新扫描扩展以进一步扩展宏。
一个 function-like 宏的参数在被插入到宏的替换文本之前完全被宏展开, 除了 它们是字符串化的操作数(#
) 或 token-pasting (##
) 运算符。因此,如果您直接调用 inner_LOAD_ATOM(buffer, ATOM_MAX)
,则在应用 #
运算符之前不会展开 ATOM_MAX
。
另一方面,当您调用 LOAD_ATOM(buffer, ATOM_MAX)
时,ATOM_MAX
宏会先于 LOAD_ATOM()
展开。 inner_LOAD_ATOM()
在那一点上没有考虑——它只是外部宏替换文本的一部分,直到 LOAD_ATOM()
的扩展为 re-scanned 以进行进一步的宏扩展。