gpt4 book ai didi

c - 如何使用具有可变数量参数的标记粘贴运算符?

转载 作者:行者123 更新时间:2023-12-04 10:16:53 25 4
gpt4 key购买 nike

我想有一个通用版本的 #define concatenate(a, b, c) a ## b ## c
我是这样试的:

#include <stdio.h>

#define concatenate(arg1, ...) arg1 ## __VA_ARGS__

int main()
{
int dob = 121201;
printf("%d", concatenate(d, o, b));

return 0;
}


我还尝试了很多其他方法:
#define concatenate(arg1, ...) arg1 ## ##__VA_ARGS__ #define concatenate(...) ## ##__VA_ARGS__ #define concatenate(...) ##__VA_ARGS__ #define concatenate(arg1, ...) arg1 ## ... #define concatenate(arg1, ...) arg1 ## concatenate(##__VA_ARGS__)
唉,我所有的尝试都失败了。我想知道是否有可能以任何方式做到这一点?

最佳答案

这是可能的。 Jens Gustedt很有趣 P99 macro library包括宏 P99_PASTE ,这正是您 concatenate 的签名,以及相同的语义。

至少可以说,P99 用来实现该功能的机制很复杂。特别是,它们依赖于数百个编号的宏,以弥补 C 预处理器不允许递归宏扩展的事实。

关于如何在 C 预处理器中进行迭代的另一个有用的解释可以在 Boost Preprocessor Library 的文档中找到。 ,特别是关于 reentrancy 的话题.

Jens 的文档 P99_PASTE强调宏从左到右粘贴的事实,以避免 ## 的歧义.这可能需要一些解释。

token 粘贴 ( ## ) 运算符是一个二元运算符;如果要将两个以上的段粘贴到单个 token 中,则需要一次进行一对,这意味着所有中间结果都必须是有效的 token 。这可能需要一定程度的谨慎。例如,考虑这个宏,它试图在整数的末尾添加一个指数:

#define EXPONENT(INT, EXP) INT ## E ## EXP

(这仅在两个宏参数都是文字整数时才有效。为了允许宏参数是宏,我们需要在宏扩展中引入另一层间接。但这不是这里的重点。)

我们几乎马上就会发现 EXPONENT(42,-3)不起作用,因为 -3不是一个单一的 token 。这是两个 token , -3 ,粘贴操作符只会粘贴 - .这将导致两个 token 序列 42E- 3 ,这最终会导致编译器错误。
42E42E-顺便说一下,是有效的 token 。它们是 ppnumbers,预处理数字,它们是点、数字、字母和指数的任意组合,前提是标记以数字开头或点后跟数字。 (指数是字母 EP 之一,可能是小写字母,并且可能后跟一个符号。否则,符号字符不能出现在 ppnumber 中。)

所以我们可以尝试通过要求用户将符号与数字分开来解决这个问题:
#define EXPONENT(INT, SIGN, EXP) INT ## E ## SIGN ## EXP

EXPONENT(42,-,3)

如果 ## 会起作用运算符从左到右计算。但是 C 标准没有强加任何特定的多个 ## 的评估顺序。运营商。如果我们使用从右到左工作的预处理器,那么它首先要做的就是粘贴 -3 ,这将不起作用,因为 -3不是一个单一的标记,就像更简单的定义一样。

现在,我不能提供一个编译器会在这个宏上失败的例子,因为我没有一个从右到左的预处理器。 gcc 和 clang 都会评估 ##从左到右,我认为这是最常见的评估顺序。但你不能依赖它;为了编写可移植的代码,您需要确保按预期顺序评估粘贴运算符。这就是 P99_PASTE 提供的保证.

备注 : 可能有一个应用程序需要从右到左粘贴,但经过一段时间的思考,我想出的唯一一个例子是 token 粘贴,它可以从右到左工作,但不能从左到右是以下相当模糊的角落情况:
#define DOUBLE_HASH %: ## % ## :

我想不出任何可能出现的合理背景。

关于c - 如何使用具有可变数量参数的标记粘贴运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61029668/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com