【问题标题】:What is #__VA_ARGS__ supposed to generate when there are no arguments passed?当没有传递参数时,#__VA_ARGS__ 应该生成什么?
【发布时间】:2014-08-21 18:37:07
【问题描述】:

示例代码:

#define FOO(...) You passed: #__VA_ARGS__
FOO(1,2,3)
FOO()

使用 Visual C++(版本 14 CTP)进行预处理,获取:

You passed: "1,2,3"
You passed:

在最后一行,#__VA_ARGS__ 变成了虚无。我宁愿把它变成“”。

对于应该发生的事情是否有明确的参考?我用谷歌搜索了很多,但找不到。

任何建议的解决方法也会很有用。

【问题讨论】:

  • 标准可能未指定。当我在gcc 的预处理器下运行时,我目前得到""
  • 您是否查看了预处理的源代码,或者您是否有可能误解了测试程序的输出?
  • 这没什么区别,不是吗?您始终可以将结果连接成您喜欢的任何字符串:"Hello: " FOO() "!\n"

标签: c++ c-preprocessor variadic-macros


【解决方案1】:

标准(ISO14882:2011(e))中的段落有点长,但很清楚:

16.3.2 # 运算符

2字符串文字 是一个 string-literal 没有 字首。如果,在替换列表中,一个参数是立即 前面有 # 预处理标记,两者都替换为单个 字符串文字预处理标记,包含 对应的预处理标记序列的拼写 争论。每次出现的参数之间的空白 预处理标记成为字符中的单个空格字符 字符串字面量。第一个预处理标记之前的空格和 在包含参数的最后一个预处理标记被删除之后。 否则,每个预处理标记的原始拼写 参数保留在字符串文字中,除了 产生字符串文字拼写的特殊处理和 字符文字:在每个 " 和 \ 之前插入一个 \ 字符 字符文字或字符串文字的字符(包括 分隔 " 字符)。如果结果的替换不是 有效的字符串文字,行为未定义。 该 空参数对应的字符串字面量是“”。 # 和 ## 运算符的求值顺序未指定。

因为

16.3.1 参数替换

2 出现在替换列表中的标识符__VA_ARGS__ 应将其视为参数,而可变参数 应形成用于替换它的预处理标记。

这对于可变参数和普通参数是一样的。

【讨论】:

  • 谢谢;我用一个简单的参数(#define FOO(x))试了一下,它的行为是一样的。
  • @Bryan:对我来说似乎是一个错误。但是微软的人喜欢把这些东西称为“特性”,所以除非你问他们(通过提交错误报告),否则我们永远不会知道。
【解决方案2】:

根据 6.10.3.2 # 运算符 (C11):

语义

2 - [...] 对应于空参数的字符串文字是""。 [...]

所以我认为这里的 MSVC 是不正确的。

我会使用字符串文字连接来解决这个问题:

#define FOO(...) You passed: "" #__VA_ARGS__

【讨论】:

  • 好吧,VC++从来没有假装完全实现C99或C11,所以很难说它是不正确的;它只是不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-24
  • 1970-01-01
  • 1970-01-01
  • 2021-01-30
  • 2019-09-26
  • 1970-01-01
  • 2012-01-03
相关资源
最近更新 更多