【问题标题】:What is the compiler seeing with this macro? [closed]编译器用这个宏看到了什么? [关闭]
【发布时间】:2012-12-10 07:05:45
【问题描述】:

考虑一下:

  #define STRINGIFY(A) #A

如果我以后再写:

 STRINGIFY(hello)

编译器是否真的看到了这个:

 #hello

我认为是 #A 前面的附加哈希让我感到困惑。

【问题讨论】:

  • 在 SO 上搜索 [C] stringify 会得到很多答案
  • “关闭为不是真正的问题”?什么不清楚?也许它是重复的,但问题很清楚:它在标题中。
  • 我不得不同意,这个问题似乎很清楚,没有歧义的余地

标签: c-preprocessor stringification


【解决方案1】:

编译器看到的是这样的:

"hello"

哈希是预处理器专用令牌。

单个哈希字符串化参数。

#define STRINGIFY(x) #x
STRINGIFY(hello)

被替换为

"hello"

双哈希连接标记:

#define CAT(a, b) a##b
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
STRINGIFY(CAT(hello,world))

被替换为:

_STRINGIFY(helloworld)

然后这样:

"helloworld"

编辑: 正如 Pubby 指出的那样,示例是错误的,宏替换不起作用,但现在我更正了。

【讨论】:

  • 那太好了,你能解释一下哈希对 OP 到底做了什么,让这个答案有点用处吗?
  • 我同意我仍然很困惑。然后第二个哈希也被预处理器解释,所以基本上预处理器在使用 STRINGIFY 时进行两种解释?
  • @andrewx 哈希只是告诉预处理器“字符串化”。
  • 临时 -1 因为STRINGIFY(CAT(hello,world)) 不会扩展为"helloworld"。参数扩展的规则很奇怪,请参阅stackoverflow.com/a/8754665/964135
【解决方案2】:

不,编译器会将参数放在引号之间,结果如下:

"hello"

但是,请注意宏替换不会发生在 ### 附近,因此如果您确实需要对参数进行字符串化(即使它是另一个宏),最好编写两个宏,第一个扩展参数,另一个添加引号:

#define STRINGIFY(x) STRINGIFY_AUX(x)
#define STRINGIFY_AUX(x) #x

或者更一般地说,如果您的编译器支持可变参数宏(在 C99 中引入):

#define STRINGIFY(...) STRINGIFY_AUX(__VA_ARGS__)
#define STRINGIFY_AUX(...) #__VA_ARGS__

如果你真的需要一个在参数开头粘贴# 的类函数宏,我认为你需要它来生成一个字符串(否则你会为编译器创建一个无效的标记),所以你可以简单地生成编译器将“粘贴”的两个字符串文字:

#include <stdio.h>

#define STRINGIFY(...) STRINGIFY_AUX(__VA_ARGS__)
#define STRINGIFY_AUX(...) #__VA_ARGS__

int main(void)
{
  puts(STRINGIFY(#) STRINGIFY(hello));
}

main 正文在预处理器输出中将如下所示:

puts("#" "hello");

我希望这不是导致未定义行为的预处理器的一个不起眼的角落,但这应该不是问题,因为我们没有生成另一个预处理器指令。

【讨论】:

    【解决方案3】:

    您可以使用-E (*) 标志(使用 gcc/g++)自行测试:

    测试.cpp

    #define STRINGIFY(A) #A
    
    int main(int argc, const char *argv[])
    {
        STRINGIFY(hello);
        return 0;
    }
    

    g++ test.cpp -E的输出

    # 1 "test.cpp"
    # 1 "<command-line>"
    # 1 "test.cpp"
    
    
    int main(int argc, const char *argv[])
    {
        "hello";
        return 0;
    }
    

    (*): If you use the -E option, nothing is done except preprocessing. - GCC Options Controlling the Preprocessor

    【讨论】:

      【解决方案4】:

      在这里找到了在预处理器中使用散列的简单简单的解释:

      http://www.cplusplus.com/doc/tutorial/preprocessor/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多