在C99标准中,第10.3.5节的示例3演示了f(已修改)的宏扩展:

#define f(a)    f(a)
#define z       z[0]
f(z)

扩展的结果是"f(z[0])",这对于MSVC和GCC也是正确的.但我不明白为什么结果不是"f(z[0][0])",这可能是以下宏展开序列的结果:

  • during arguments macro expansion, z argument is replaced with z[0]:
    f(z[0])
  • "f(z[0])" is replaced with "f(z[0])":
    f(z[0])
  • during rescan, z is replaced with z[0] again:
    f(z[0][0])

这显然与正确的结果不同.Z的两个展开是完全分开的,因此不适用递归预防.但是,不会执行其中一个z展开.为什么?

请帮助我理解我错在哪里

显然,所有的预处理器都会产生正确的结果,所以了解这里到底发生了什么对我来说很重要.

推荐答案

我知道你的困惑从何而来.这不是标准的官方来源,但来自GCC,应该有足够的权威性来解释正在发生的事情.这里有一段话就是指你的案子.

您可能会期望双重扫描改变结果, 自引用宏用于另一个宏的参数中(请参见 自引用宏):自引用宏将被扩展 一次在第一次扫描中,第二次在第二次扫描中.然而, 事情不是这样的self 指涉不会在 第一次扫描被标记,使得它们不会在第二次扫描中扩展. 扫描也可以.

在 compose 本文时,这是第https://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html段中的第三段

C++相关问答推荐

从STdin读写超过4096个字节

intellisense不工作,甚至已经下载了c/c++扩展

标准的C17标准是用括号将参数包装在函数声明中吗

C编译器是否遵循restrict的正式定义?

如何在C中使printf不刷新标准输出?

是否可以使用指针算法在不对齐的情况下在 struct 中相同类型的字段的连续序列之间移动?

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

从TCP连接启动UDP(C套接字)

在C中包装两个数组?

如何使用FSeek和文件流指针在C中查找文件的前一个元素和前一个减go 一个元素

C将数组传递给函数以修改数组

C程序向服务器发送TCPRST

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

为什么我无法访问C语言中的文件

通过GTK';传递回调参数;s g_signal_connect()导致C中出现意外值

程序打印一些随机空行

C 语言中 CORDIC 对数的问题

在 C/C++ 中原子按位与字节的最佳方法?

我该如何处理这个 C 90 代码中的内存泄漏?

如何让 unlinkat(dir_fd, ".", AT_REMOVEDIR) 工作?