4

可能重复:
将预处理器标记转换为字符串

#define num 1234

我想基于 num 定义一个“const char*”,在示例中它将是:

#define num_str "1234"

我可以写一个宏语句来实现这个吗?注意:1234 将被更改。

谢谢。

4

2 回答 2

3

是的,你可以,但是宏替换看起来有点奇怪。双宏替换是有原因的,如果你仔细考虑一下,就会清楚为什么需要它。

#define STRINGIZER_(exp)   #exp
#define STRINGIZER(exp)    STRINGIZER_(exp)
#define NUM 1234

int main(int argc, char *argv[])
{
    const char *p = STRINGIZER(NUM);
    printf("%s\n",p);
    return EXIT_SUCCESS;
}

运行这个:

1234

双重替换的原因:乍一看可能会认为这样可以解决问题:

#define STRINGIZER(exp)    #exp
#define NUM 1234

int main(int argc, char *argv[])
{
    const char *p = STRINGIZER(NUM);
    printf("%s\n",p);
    return EXIT_SUCCESS;
}

但这会产生:

NUM

这不是我们想要做的。如果您想首先实际扩展 NUM 宏,那么您必须这样做:强制扩展。通过强制预处理器首先通过中间扩展进行替换(如我在此答案顶部所示),传入的宏首先被扩展,然后是字符串化的。

侧栏:该技术对于生成预定义的预处理器宏的宽字符版本特别有用,否则这些宏会保存常规字符串。例如,__FILE__宏。假设你想要一个宽字符版本(一个以 'L' 开头的字符串)你可能首先认为这会起作用:

#define WIDESTR(str)    L##str

但将其扩展__FILE__为:

const wchar *p = WIDESTR(__FILE__);

将导致编译器错误:"Undefined identifier: L__FILE__"

那么我们该如何解决这个问题呢?和我们上面做的一样。

#define WIDESTR_(str)       L##str
#define WIDESTR(str)        WIDESTR_(str)

int main(int argc, char *argv[])
{
    const wchar_t* p = WIDESTR(__FILE__);
    wcout << p << endl;
    return EXIT_SUCCESS;
}

在我的系统上,这会产生:

/Users/craig/tmp/main/main/test.cpp

在关闭...

作为安慰奖,我们将这个答案中的所有内容组合成一个巨大的粘性物,我们假设这样做会发生什么

int main()
{
    const wchar_t *p = WIDESTR(STRINGIZE(NUM));
    wcout << p << endl;
    return EXIST_SUCCESS;
}
于 2012-11-01T07:23:05.433 回答
0

该字符串将如何在您的其余代码中使用?它必须是字符串宏吗?从其他值创建字符串的标准方法是使用 string.h 中的 sprintf()

#define num 1234
sprintf(string,"%d",num);
于 2012-11-01T07:25:23.030 回答