当#defines正在使用其他#defines时,顺序是否重要?

时间:2014-03-22 08:36:07

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

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

#define three 3
#define nine three*3

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

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

#define nine three*3
#define three 3

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

同样编译并运行正常,并打印“9”。

我的编译器是否让我轻松,或者使用其他#define的#defines确实无关紧要?编译是否会在一个更复杂的项目中失败?

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

4 个答案:

答案 0 :(得分:8)

只需在使用three宏之前定义

nine宏。 您甚至可以在每次使用three之前更改nine

#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;
}

答案 1 :(得分:3)

预处理器执行多次运行,只有在未找到所有定义的其他定义时才结束。因此,您的代码示例都可以工作,但预处理器需要再运行一次,如果是第二个。你必须小心递归定义。然后ppc永远不会退出。

答案 2 :(得分:3)

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

  

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

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

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

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

答案 3 :(得分:0)

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