#define foo 123

foo
_foo
->foo
&foo

在上面的文件上运行gcc -E会输出以下内容:

123
_foo
->123
&123

这表明_不是记号分隔符,而_foo是一个完整的单词. 在哪里可以找到C预处理器的有效令牌分隔符的列表?

推荐答案

我可能会被语言律师烤熟.但我是这么读这份说明书的.

关于ANidentifier token,这是预处理器关心的WRT到#define替换以及编译器本身的问题.它不包括字符串文字.标识符令牌是以字母(a-zA-Z)或下划线(_)开头的任意序列,后跟任意数量的字母、数字或下划线.换句话说,下划线标识令牌的方式与任何其他字母或数字相同.

或者稍微正式一点(但不完美),标识符令牌是这个正则表达式:

[a-zA-Z_]([a-zA-Z0-9_])*

换句话说,下划线只是另一个字母.

与上面的正则表达式不匹配的任何其他标记都是另一种类型的标记(字符串、空格、运算符、圆括号等).

把这一切带回家.

这些表达式如下:

foo
_foo
->foo
&foo
"foo"
foo456
5foo

解析为:

identifier (foo)
identifier (_foo)
operator (->) followed by identifier (foo)
operator (&) followed by identifier (foo)
string literal ("foo")
identifier (foo456)
invalid identifier: (5foo).

执行#define foo 123替换的预处理器将匹配名为foo的标识符.它不会将foo456扩展到123456,也不会将_foo扩展到_123,因为它们是完全不同的标识符名.

我对5foo不是5foo%肯定,但无论如何我看不出它被认为是有效的标识符令牌.或者更准确地说,它是一个无效的数字令牌.

来源:C++草案标准(https://isocpp.org/files/papers/N4860.pdf)第5.4节是的,我知道这个问题被标记为C,但它应该足够匹配.

C++相关问答推荐

为什么在C中进行大量的位移位?

增加getaddrinfo返回的IP地址数量

如果包含路径不存在,我的编译器可以被配置为出错吗?(GCC、MSVC)

当我运行/调试C程序时,Malloc()似乎正在将&q;r\r...&q;赋值给一个指针,我不确定为什么?

在传统操作系统上可以在虚拟0x0写入吗?

Rust FFI--如何用给出返回引用的迭代器包装C风格的迭代器?

S将C语言宏定义为自身的目的是什么?(在glibc标题中看到)

==284==错误:AddressSaniizer:堆栈缓冲区下溢

#定义SSL_CONNECTION_NO_CONST

C I/O:在Windows控制台上处理键盘输入

指向不同类型的指针是否与公共初始序列规则匹配?

链接到底是如何工作的,我在这里到底做错了什么

在vfork()之后,链接器如何在不 destruct 父内存的情况下解析execve()?

如何将C中的两个字符串与从文件接收的字符串中的字符数进行比较

C语言中神秘的(我认为)缓冲区溢出

递归打印二维数组(C编程)

用C++高效解析HTTP请求的方法

GETS()在C++中重复它前面的行

为什么 C 字符串并不总是等同于字符数组?

nullptr_t 是否会 destruct 类型双关或指针转换?