2

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

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

宏“MAKE_STRING”传递了 2 个参数,但只需要 1 个

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

4

3 回答 3

1

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

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

于 2014-03-24T13:23:53.800 回答
-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
于 2014-03-24T11:39:20.560 回答
-2

我不知道为什么这有赞成票,或者答案被反对(所以海报删除了它)但我不知道你期望什么!

#__VA_ARGS__没有意义,假设我有 MACRO(a,b,c) 你想要 "a,b,c" 作为字符串吗?

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

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

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

笔记:

阅读该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);
于 2014-03-24T11:50:31.543 回答