首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C如何在宏替换列表的末尾展开类似函数的宏?

C如何在宏替换列表的末尾展开类似函数的宏?
EN

Stack Overflow用户
提问于 2021-11-18 10:00:10
回答 1查看 194关注 0票数 6

可以使用以下构造来迭代预处理前序列:

代码语言:javascript
复制
#define A() B
#define B() A
A()()()()()

扩展到大多数编译器/预处理器上的B:clang、gcc、tcc、chibicc、SDCC (我无法测试msvc,因为它没有在龙芯上工作,但如果您想测试它,请确保使用/Zc:preprocessor标志,因为否则预处理器将不是条件)。

阅读6.10.3.4似乎表明,B的扩展发生在A内部,这将导致A的第二次扩展不会发生,而是被涂成蓝色,扩展将停止。

6.10.3.4恢复和进一步更换 在替换列表中的所有参数被替换并进行了#和##处理之后,所有placemarker预处理标记都被删除。得到的预处理令牌序列然后与源文件的所有后续预处理令牌一起重新包装,以获得更多要替换的宏名称。

但附件J.1指出,无论是否使用嵌套完成,都是未具体说明的行为:

当一个完全展开的宏替换列表包含一个类似函数的宏名称作为其最后的预处理令牌时,源文件中的下一个预处理令牌是一个(,该宏的完全展开替换以第一个宏的名称结束,而来自源文件的下一个预处理令牌)再次是a(不管它是否被认为是嵌套替换(6.10.3)。

好的,公平,所以大多数预处理器使用非嵌套的方法,但是什么允许下面的工作呢?

代码语言:javascript
复制
#define A() B(
#define B() A(
A()))))

现在假设前者会给您一个错误,对于一个“未终止的参数列表调用宏'B'",但是您不认为这会扩展到A())),在那里,A现在被画成蓝色,这不应该会产生错误吗?

而且,您可以通过检测最后一个结束括号来消除错误。,显示这似乎也没有使用嵌套,这是奇怪的,因为标准在哪里表明这是有效的?

所以已经有了类似的问题,但我不认为答案与这个问题有什么关系,因为引文只是在谈论参数替换:

6.10.3.1论点替代 在确定了调用类似函数的宏的参数之后,就会发生参数替换。替换列表中的参数,除非前面有#或##预处理令牌,或者后面跟着一个##预处理令牌(请参阅下面),则在展开其中包含的所有宏之后,将替换相应的参数。在被替换之前,每个参数的预处理令牌都会被宏完全替换,就好像它们构成了预处理文件的其余部分一样;没有其他的预处理标记可用。

这是有意义的,因此在#define A(x) x x x中,传递给A的参数x只需要在日照下展开一次,然后就会在展开列表中插入生成的令牌来代替x的出现。

这也解释了以下行为:

代码语言:javascript
复制
#define STR(x) #x
#define f(x) x
#define F(x) STR(x(23))
F(f) // expands to "f(23)"

因此,孤立的部分指的是参数本身,而不是重新封装中发生的情况,这在6.10.3.4中有详细说明,这是我最初的标准引用。

那么,这里发生了什么,我应该如何看待宏观扩张过程呢?

EN

回答 1

Stack Overflow用户

发布于 2022-09-25 07:18:46

从我对DR17的阅读中可以看出,如果)是与左侧展开的结果相结合的,那么它在标准中是故意不指定的。行为是未定义的。严格一致的程序不应该使用这个。

为什么宏名没有涂成蓝色?017.htmlhttps://port70.net/%7Ensz/c/c11/n1570.html#6.10.3.4p4

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70017827

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档