2014-03-24 47 views
2

我正在使用字符串化运算符来转换参数,其中可能包含逗号传递给一个宏字符串。据我所知,有些字符不能字符串 - 特别是逗号(,),因为它用于分隔参数和右括号()),因为它标记了参数的结尾。所以我使用可变宏来将逗号传递给字符串操作符,如下所示:visual C++与gcc/clang不同的行为,而stringify参数包含逗号

#include <stdio.h> 

#define TEST 10, 20 

#define MAKE_STRING(...) #__VA_ARGS__ 
#define STRING(x)  MAKE_STRING(x) 

int main() 
{ 
    printf("%s\n", STRING(TEST)); 
    return 0; 
} 

它工作正常。但是,它发生在没有可变宏的情况下会发生什么,所以我修改宏:#define MAKE_STRING(x) #x。它编译在Visual C++ 2008/2010,输出10, 20意外细而GCC /铛给预期的编译错误:

宏 “MAKE_STRING” 经过2个参数,但只需1

所以我的问题:是Visual C++做额外的工作或行为是未定义的?

+0

@AlecTeal也许他的意思是字符串化 – WileTheCoyot

+0

@WileTheCoyot你不能用__VA_ARGS__做--GCC有一个特例 - 保持。 –

+1

@WileTheCoyot不会删除你的答案!你有好东西在里面!你说的是对的! OP要废话! –

回答

-1

我不确定这是否会回答你的问题,但我希望这会帮助你解决你的问题。在C中定义一个字符串常量时,应该用双引号(空格)包含它。此外,#宏将变量名称包含在双引号内,因此,例如,#a变为"a"

#include <stdio.h> 

#define TEST "hello, world" 
#define MAKE_STRING(x) #x 

int main() 
{ 
    int a; 
    printf("%s\n", TEST); 
    printf("%s\n", MAKE_STRING(a)); 
    return 0; 
} 

我使用gcc 4.7.1编译的代码,输出为:

hello, world 
a 
+0

代表是非常随意的,所以如果你有一个帖子来展示某个来自未来的人可能会喜欢阅读的东西;把它留下。就像有人问C++中带有按钮的图形用户界面一样,他们之后添加了它必须是Windows API,所以我添加了一段同情心,并留下了关于wxWidgets提供可爱API的答案:P这很有用,是'#'的意思,OP要废话! –

+0

@AlecTeal非常感谢您的提示 – WileTheCoyot

+0

我不需要一个常量字符串,它只是一个测试。 – jfly

-2

我不知道为什么这次却upvotes,或答案得到downvoted(所以海报删除了),但我不不知道你期望什么!

#__VA_ARGS__是没有意义的,假设我有MACRO(A,B,C)你想 “A,B,C” 的字符串?

http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html#Variadic-Macros

阅读,成为标准的行为,在宏可变长度参数允许他们在可变长度参数做什么功能。预处理器按文本操作!

涉及#唯一的特例是##,如果没有额外的参数(从而避免语法错误)

注意其删除##前的逗号:

这是非常重要的你读了MACRO(a,b,c)部分,你期望什么,字符串“a,b,c”?或 “A,B,C”,如果你想字符串 “A,B,C” 写入字符串 “A,B,C”

使用#运营商的东西大如

#define REGISTER_THING(THING) core_of_program.register_thing(THING); printf("%s registered\n",#THING); 
+2

'#__ VA_ARGS__'是合法的。 6.10.3.1/2:“在替换列表中出现的标识符__VA_ARGS__应被视为参数......”6.10.3.2/1:“替换列表中的每个”#“预处理标记,像宏应该是 ,然后是一个参数作为替换列表中的下一个预处理标记。“这两项要求均符合。 – ach

+0

我已经知道你在上面说了什么,问题是为什么代码在vC++中没有可变宏的情况下工作。 – jfly

+0

不确定我同意@AndreyChernyakhovskiy - '__VA_ARGS__'不仅仅是在括号或逗号之前出现在另一个括号之前的文本,它可能有些时候表现得像它,但它不是。 http://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification和其他页面是我的信息的来源,我倾向于坚持GNU扩展和类似的东西,并回落到标准,因为它通常(有用的和功能性的)(比如“有利于完成工作”而不是编程风格)的增加。 –

1

一般情况下,VS允许在宏中使用额外的参数,然后以静默方式丢弃它们: STRING(10, 20, 30) - 仍然有效并打印10。这里不是这种情况,但它几乎意味着VS甚至没有gcc向你抛出的错误。

这不是任何额外的工作,而是“仅仅”替代顺序的差异。