【问题标题】:Does order matter when #defines are using other #defines?当#defines 使用其他#defines 时,顺序是否重要?
【发布时间】:2014-04-29 19:08:55
【问题描述】:

根据this question的回答,以下代码是合法的:

#define three 3
#define nine three*3

int main()
{
    std::cout << nine;
    return 0;
}

当然,它编译并运行良好。但是,对上述问题的回答还指出,应注意此类#define 指令的顺序,并且应在它们之前定义将在其他#defines 中使用的指令。但是下面的代码:

#define nine three*3
#define three 3

int main()
{
    std::cout << nine;
    return 0;
}

也编译和运行良好,它打印“9”。

我的编译器让我轻松了吗,或者使用其他#defines 的#defines 的顺序确实无关紧要?在更复杂的项目上编译会失败吗?

值得一提的是,上面提到的问题是关于 C,而我的代码是 C++。这就是(假定的)行为差异的来源吗?

【问题讨论】:

  • 查看 Chris Dodds 在链接问题中的回答。
  • @erenon 哦,确实,它更深入地了解了这个机制。很好,你指出了。
  • 一个更复杂的项目并不意味着更复杂的宏。您可以获得具有复杂宏的小项目和具有简单宏的大项目。

标签: c++ c-preprocessor operator-precedence


【解决方案1】:

three 宏只需要在使用nine 宏之前定义。 您甚至可以在每次使用 nine 之前更改 three

#define nine three*3
#define three 3

int main()
{
    std::cout << nine; //9
#undef three
#define three 4
    std::cout << nine; //12
#undef three
    //no `three` macro defined here
    int three = 2;
    std::cout << nine; //three * 3 == 6
    return 0;
}

【讨论】:

    【解决方案2】:

    预处理器进行多次运行,并且仅在没有找到所有定义的其他匹配项时完成。因此,您的代码示例都可以工作,但预处理器需要再运行一次,以防第二次运行。您必须小心递归定义。然后 ppc 将永远不会退出。

    【讨论】:

    • 你不能让预处理器做无限循环。当他发现他之前扩展的相同标记时,他停下来。例如。 #define Foo Foo 导致Foo
    【解决方案3】:

    这些步骤将在预处理器步骤中完成,所有文字都将替换为它们的值。如果我们使用以下选项进行编译,则可以验证这一点:

    $ g++ -save-temps basic.cpp -o out

    这是预处理步骤后的输出(basic.ii 文件):

    int main()
    {
        std::cout << 3*3;
        return 0;
    }
    

    为您的示例程序。所以顺序应该无关紧要,因为它是一种查找和替换,它是在程序实际编译之前完成的。

    【讨论】:

      【解决方案4】:

      实际上是因为两步解析器。在第一步中,它尝试解析所有符号,并在第二步中放置实际值。

      【讨论】:

        猜你喜欢
        • 2010-10-21
        • 2014-12-17
        • 2013-06-28
        • 1970-01-01
        • 2011-03-12
        • 2011-07-12
        • 2010-10-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多