在使用包含逗号的字符串化参数时,visual c ++与gcc / clang的行为不同

时间:2014-03-24 11:01:08

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

我使用字符串化运算符将可能包含传递给宏的逗号的参数转换为字符串。据我所知,有些字符不能被字符串化 - 特别是逗号(,),因为它用于分隔参数和右括号()),因为它标记了参数的结尾。所以我使用一个可变参数宏将逗号传递给字符串化运算符,如下所示:

#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 / clang按预期给出编译错误:

  

宏&#34; MAKE_STRING&#34;传递了2个参数,但只需1个

所以我的问题是:Visual c ++正在做额外的工作还是行为未定义?

3 个答案:

答案 0 :(得分:1)

VS通常允许在宏中使用额外的参数,然后只是静默地删除它们: STRING(10, 20, 30) - 仍然有效并打印10。这不是这里的情况,但它几乎意味着VS甚至没有gcc向你投掷的错误。

这不是任何额外的工作,而是&#34;仅仅&#34;替代顺序的差异。

答案 1 :(得分:-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

答案 2 :(得分:-2)

我不知道为什么这会有投票,或者答案得到了落实(所以海报删除了它)但我不知道你的期望!

#__VA_ARGS__毫无意义,假设我有MACRO(a,b,c)你想要&#34; a,b,c&#34;作为字符串?

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

读取,这成为标准行为,宏中的可变长度参数允许它们在函数的可变长度参数中执行的操作。预处理器在文本上运行!

唯一涉及#的特殊情况是##,如果没有额外的参数,则删除##之前的逗号(从而防止语法错误)

注意:

阅读MACRO(a,b,c)部分非常重要,您期望什么,字符串&#34; a,b,c&#34;?或&#34; a,b,c&#34;如果你想要字符串&#34; a,b,c&#34;写字符串&#34; a,b,c&#34;

使用#运算符非常适合像

这样的内容
#define REGISTER_THING(THING) core_of_program.register_thing(THING); printf("%s registered\n",#THING);