C++ a中的定义是什么意思?

C++ a中的定义是什么意思?,c++,c,c-preprocessor,C++,C,C Preprocessor,这条线是什么意思?特别是,##是什么意思 #define ANALYZE(variable, flag) ((Something.##variable) & (flag)) #定义分析(变量,标志)((某物.##变量)和(标志)) 编辑: 还是有点困惑。如果没有##,结果会是什么?##称为令牌连接,用于在宏调用中连接两个令牌 见此: 根据维基百科的说法 令牌连接,也称为令牌粘贴,是C宏预处理器最微妙、最容易滥用的特性之一。可以使用##预处理器运算符将两个参数“粘合”在一起;这允许在预

这条线是什么意思?特别是,
##
是什么意思

#define ANALYZE(variable, flag) ((Something.##variable) & (flag)) #定义分析(变量,标志)((某物.##变量)和(标志)) 编辑:


还是有点困惑。如果没有
##
,结果会是什么?

##
称为令牌连接,用于在宏调用中连接两个令牌

见此:

  • 根据维基百科的说法

    令牌连接,也称为令牌粘贴,是C宏预处理器最微妙、最容易滥用的特性之一。可以使用##预处理器运算符将两个参数“粘合”在一起;这允许在预处理代码中连接两个令牌。这可以用来构造精细的宏,它的功能类似于C++模板的粗版本。
    检查

    一个非常重要的部分是,此令牌连接遵循一些非常特殊的规则:

    e、 g.IBM文档:

    • 连接发生在任何 参数中的宏将展开
    • 如果串联的结果是 有效的宏名称,可用于 进一步更换,即使 出现在它所处的上下文中 通常不可用
    • 如果不止一个##运算符和/或# 操作员出现在替换中 宏定义的列表,顺序 对经营者的评价是不公平的 已定义。
    例子也很能自我解释

    #define ArgArg(x, y)          x##y
    #define ArgText(x)            x##TEXT
    #define TextArg(x)            TEXT##x
    #define TextText              TEXT##text
    #define Jitter                1
    #define bug                   2
    #define Jitterbug             3
    
    输出:

    ArgArg(lady, bug)   "ladybug"
    ArgText(con)    "conTEXT"
    TextArg(book)   "TEXTbook"
    TextText    "TEXTtext"
    ArgArg(Jitter, bug)     3
    
    源代码是IBM文档。可能因其他编译器而异

    到您的线路:

    它将变量属性连接到“Something.”并处理一个逻辑上为and的变量,如果Something.variable设置了标志,则会给出结果

    我的最后一个评论和你的问题的一个例子(可使用g++编译):

    //此操作失败,出现编译器错误
    //定义分析1(变量、标志)((某物、变量)和(标志))
    //这个可以解决一些问题。a(struct)
    #定义ANALYZE2(变量,标志)((Something.variable)和(标志))
    //这将是一个(全球的)
    #定义分析3(变量、标志)((某物、变量)和(标志))
    #包括
    使用名称空间std;
    构造某物{
    INTA;
    };
    int Somethinga=0;
    int main()
    {
    某物;
    a=1;
    如果(分析2(a,1))
    库特
    
    还是有点困惑。没有###会有什么结果

    通常,您不会注意到任何差异。但有一个差异。假设
    某物属于以下类型:

    struct X { int x; };
    X Something;
    
    看看:

    int X::*p = &X::x;
    ANALYZE(x, flag)
    ANALYZE(*p, flag)
    
    如果没有令牌连接运算符
    ##
    ,它将扩展为:

    #define ANALYZE(variable, flag)     ((Something.variable) & (flag))
    
    ((Something. x) & (flag))
    ((Something. *p) & (flag)) // . and * are not concatenated to one token. syntax error!
    
    #define ANALYZE(variable, flag)     ((Something.##variable) & (flag))
    
    ((Something.x) & (flag))
    ((Something.*p) & (flag)) // .* is a newly generated token, now it works!
    
    通过令牌连接,它扩展到:

    #define ANALYZE(variable, flag)     ((Something.variable) & (flag))
    
    ((Something. x) & (flag))
    ((Something. *p) & (flag)) // . and * are not concatenated to one token. syntax error!
    
    #define ANALYZE(variable, flag)     ((Something.##variable) & (flag))
    
    ((Something.x) & (flag))
    ((Something.*p) & (flag)) // .* is a newly generated token, now it works!
    

    <> P>重要的是要记住预处理器在预处理器令牌上运行,<强> >不/强>文本。因此,如果要连接两个令牌,必须明确地表示它。

    让我们考虑另一个例子:

    考虑

    #define MYMACRO(x,y) x##y
    
    如果没有
    ##
    ,预处理器显然无法将
    x
    y
    视为单独的标记,不是吗

    以你为例,

    #define ANALYZE(variable, flag)     ((Something.##variable) & (flag))
    

    ##
    根本不需要,因为您没有创建任何新的标识符。事实上,编译器会发出“错误:粘贴”和“变量”没有给出有效的预处理标记“

    这不是对您问题的回答,只是一篇CW帖子,其中有一些提示,可以帮助您自己探索预处理器

    预处理步骤实际上是在编译任何实际代码之前执行的。换句话说,当编译器开始编译代码时,不会留下任何#define语句或类似的语句

    了解预处理器对代码做了什么的一个好方法是掌握预处理的输出并查看它

    这是Windows的操作方法:

    创建一个名为test.cpp的简单文件,并将其放在一个文件夹中,例如c:\temp。 我的看起来像这样:

    #define dog_suffix( variable_name ) variable_name##dog
    
    int main()
    {
      int dog_suffix( my_int ) = 0;
      char dog_suffix( my_char ) = 'a';
    
      return 0;
    }
    
    #line 1 "test.cpp"
    
    
    int main()
    {
      int my_intdog = 0;
      char my_chardog = 'a';
    
      return 0;
    }
    
    不是很有用,但很简单。打开Visual studio命令提示符,导航到该文件夹并运行以下命令行:

    c:\temp>cl test.cpp /P
    
    因此,您运行的编译器(cl.exe)与您的文件一起运行,/p选项告诉编译器将预处理的输出存储到文件中

    现在,在test.cpp旁边的文件夹中,您将找到test.i,它对我来说如下所示:

    #define dog_suffix( variable_name ) variable_name##dog
    
    int main()
    {
      int dog_suffix( my_int ) = 0;
      char dog_suffix( my_char ) = 'a';
    
      return 0;
    }
    
    #line 1 "test.cpp"
    
    
    int main()
    {
      int my_intdog = 0;
      char my_chardog = 'a';
    
      return 0;
    }
    

    正如您所看到的,没有定义,只剩下它扩展成的代码。

    还可以看到:事实上,它被称为令牌连接。我不认为IBM AIX C/C++编译器的文档是最好的参考!@David:将此添加到我的答案中。谢谢:-)@David:我没有说IBM AIX C/C++编译器是最好的参考。最好的参考什么都不是除了标准本身。但我们还是提供了指向其他站点的链接,包括stackoverflow的主题。对于这样的问题,标准是一个毫无希望的参考。我不确定什么是好的参考。也许IBM AIX参考中的文本是好的,但很遗憾,他们无法获得正确的名称!如果没有
    ##?所以我的测试结果是.Gcc抱怨
    a.##b
    a.##b
    对全局变量求值。
    a.b
    也对结构实例a中的变量求值。我添加了一个示例作为补充。