我很确定这个答案是重复的,但我找不到任何相关的东西,所以...我有这样一个宏:

#define MACRO(x) #x

它是否被允许这样做:

const char *var = MACRO(file.);

const char *var = MACRO(.ext);

或 use both dots:

const char *var = MACRO(.field.);

GCC and clang do compile it and run it properly, but acc或ding to C standard which characters are allowed to be used in macro parameters. Are there characters that I can't use f或 this 或 any ASCII character is allowed? And which paragraph of C standard says it?

推荐答案

在C程序的翻译过程中,源代码被解析为preprocessor tokens个空格字符序列,并且每个注释都被更改为一个空格,符合C 2018 5.1.1.2.根据C 2018 6.10.3 10,宏替换在此序列预处理器标记和空白字符上操作,而不是在原始文本上操作.

问题中显示的宏的参数必须是预处理器令牌和空白字符的列表,不带空格逗号(因为逗号表示C 2018 6.10.3 11中的第二个参数,但宏定义时只有一个参数).

因此,开始时,MACRO(,)MACRO(a,b)不是宏的定义调用.也不能在参数中包含单独的右括号,因为它会被视为参数列表的末尾.(您可以使用嵌套的左括号和右括号对,如MACRO(a(b,c)d)中所示.请注意,这里的逗号由圆括号"保护",第一个)被视为参数内开始(的结束,而不是宏参数的结束.)

预处理器标记在C 2018 6.4 1中定义,它指的是C标准中其他地方定义的语法标记:identifierpp-numbercharacter-constantstring-literalpunctuator,以及每个不能是上述之一的非空白字符.(6.4还包括header-name,但根据C 2018 6.4 4,这仅用于#include#pragma指令.

因此,要知道宏调用中定义了哪些字符序列,您需要考虑每个语法标记.

注意:该列表中的最后一个选项并不意味着允许任何字符.C实现具有一些源字符集,并且文件中可能存在未映射到源字符集中的任何字符的物理字符,编译器可能会拒绝此类字符.

除了这些被排除的字符之外,最后一个选项意味着很多东西将被接受为预处理器标记和空白的序列,因为任何不形成常规预处理标记的非排除字符序列都可以被视为"不能是上述之一的非空白字符".然而,具体说明什么是有效的是棘手的.由于预处理标记包括头名称、字符常量和字符串文字,因此上面提到的有问题的字符(逗号和括号)可能会相互作用,成为其中一个标记的一部分,而不是作为宏参数分隔符或终止符的独立字符.

在C 2018 6.10.3 11中,另一个行为显式未定义的序列是一个包含预处理指令的序列,如:

MACRO(
    #define X Y
)

此外,在宏中使用#运算符时,结果必须形成有效的字符串文字.例如,MACRO(\)的形式为"\",这不是有效的字符串文字.同样对于#,空白字符序列将被单个空格取代,因此MACRO(aXb),其中X是空格、制表符和换行符的序列将仅变为a b.

C++相关问答推荐

无效使用未定义类型'structsquare'?

GCC:try 使用—WError或—pedantic using pragmas

括号中的堆栈实现错误问题

当多个线程在C中写入相同的文件描述符时,如何防止争用情况?

LibpCap禁用监视器模式(C、MacOS)

我在这里正确地解释了C操作顺序吗?

如何在ASM中访问C struct 成员

预处理器宏扩展(ISO/IEC 9899:1999(E)§;6.10.3.5示例3)

为什么realloc函数在此代码中修改变量?

如果格式字符串的内存与printf的一个参数共享,会发生什么情况?

GetText不适用于包含国际字符的帐户名称

如何在C中用bool进行文件I/O?

如何使用WRITE()以指针地址的十六进制形式写入标准输出

强制GCC始终加载常量(即只读),即使启用了优化

';malloc():损坏的顶部大小';分配超过20万整数后

可以对两种 struct 类型中的任何一种进行操作的C函数

在哪里可以找到叮当返回码的含义?

如何在Rust中处理C的longjmp情况?

macos/arm64 上地址空间不使用第一位吗?

为什么实现文件中的自由函数默认没有内部链接?