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,表明它允许#存在并且不执行特殊处理.但是,由于#运算符的定义在这种情况下没有定义行为,它实际上是未定义的行为吗?
正如您所注意到的,#仅在类似函数的宏中具有定义的效果。\xc2\xa7 6.10.3.2/1(所有对该标准的引用均参考 C11 草案 ( N1570 ))。要了解类似对象的宏中会发生什么,我们必须看看其他地方。
\n\n\n表单的预处理指令
\n\nRun Code Online (Sandbox Code Playgroud)\n\n# define identifier replacement-list new-line\n定义\n 类似对象的宏,\n 导致宏名称的每个后续实例\n 被替换为构成指令剩余部分的预处理标记的替换列表。[...]
\n
\xc2\xa7 6.10.3/9
\n\n因此,唯一的问题是是否#允许在replacement-list. 如果是,则照常参与替换。
我们在\xc2\xa7 6.10/1中找到语法:
\n\n# define identifier replacement-list new-line\nRun Code Online (Sandbox Code Playgroud)\n\n现在,#有效吗preprocessing-token?\xc2\xa7 6.4/1说:
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\nRun 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)。
punctuator但是,它在\xc2\xa7 6.4.6/1中列为 a 。因此,它在replacement-list类似对象的宏中是允许的,并且将被逐字复制。现在需要重新扫描,如\xc2\xa7 6.10.3.4中所述。让我们看看你的例子:
C(A)将被替换为C(X#Y). #在这里没有特殊效果,因为它不在 of 中replacement-list,C而是在其参数中。C(X#Y)显然是变成了B(X#Y)。然后\'s 参数通过\'s中的运算B符转换为字符串文字,产生#Breplacement-list"X#Y"
因此,您没有未定义的行为。
\n| 归档时间: |
|
| 查看次数: |
311 次 |
| 最近记录: |