对象式宏中单个哈希的影响

M.M*_*M.M 5 c language-lawyer c-preprocessor

#允许在一个类对象宏,如果是的话,会发生什么?

所述Ç标准只定义的行为#在对函数宏的宏.

示例代码:

#include <stdio.h>

#define A X#Y
#define B(X) #X
#define C(X) B(X)

int main()
{
    printf(C(A) "\n");
}
Run Code Online (Sandbox Code Playgroud)

gcc输出X#Y,表明它允许#存在并且不执行特殊处理.但是,由于#运算符的定义在这种情况下没有定义行为,它实际上是未定义的行为吗?

hlt*_*hlt 3

正如您所注意到的,#仅在类似函数的宏中具有定义的效果。\xc2\xa7 6.10.3.2/1(所有对该标准的引用均参考 C11 草案 ( N1570 ))。要了解类似对象的宏中会发生什么,我们必须看看其他地方。

\n\n
\n

表单的预处理指令

\n\n
# define identifier replacement-list new-line\n
Run Code Online (Sandbox Code Playgroud)\n\n

定义\n 类似对象的宏,\n 导致宏名称的每个后续实例\n 被替换为构成指令剩余部分的预处理标记的替换列表。[...]

\n
\n\n

\xc2\xa7 6.10.3/9

\n\n

因此,唯一的问题是是否#允许在replacement-list. 如果是,则照常参与替换。

\n\n

我们在\xc2\xa7 6.10/1中找到语法:

\n\n
# define identifier replacement-list new-line\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,#有效吗preprocessing-token\xc2\xa7 6.4/1说:

\n\n
preprocessing-token:\n    header-name\n    identifier\n    pp-number\n    character-constant\n    string-literal\n    punctuator\n    each non-white-space character that cannot be one of the above\n
Run Code Online (Sandbox Code Playgroud)\n\n

它肯定不是 a header-name( \xc2\xa7 6.4.7/1identifier ),它在标记中不允许( \xc2\xa7 6.4.2.1/1 ),也不是 a pp-number(基本上是任何数字允许的格式,\xc2\xa7 6.4.8/1),也不是 a character-constant(例如u\'c\'\xc2\xa7 6.4.4.4/1)或 a string-literal(正是您所期望的,例如L"String"\ xc2\xa7 6.4。 5/1)。

\n\n

punctuator但是,它在\xc2\xa7 6.4.6/1中列为 a 。因此,它在replacement-list类似对象的宏中是允许的,并且将被逐字复制。现在需要重新扫描,如\xc2\xa7 6.10.3.4中所述。让我们看看你的例子:

\n\n

C(A)将被替换为C(X#Y). #在这里没有特殊效果,因为它不在 of 中replacement-listC而是在其参数中。C(X#Y)显然是变成了B(X#Y)。然后\'s 参数通过\'s中的运算B符转换为字符串文字,产生#Breplacement-list"X#Y"

\n\n

因此,您没有未定义的行为。

\n