来自C ++宏中的相互引用的奇怪结果

时间:2015-03-21 13:01:08

标签: c++ c-preprocessor

考虑以下C ++代码:

#include <bits/stdc++.h>
using namespace std;

string TRUE = "true";
string FALSE = "false";

#define TRUE FALSE
#define FALSE TRUE

int main()
{
    cout << TRUE << endl;
    cout << FALSE << endl;
}

使用GCC 4.9.2编译,上面的代码输出:

true
false

生产输出背后的逻辑是什么?我期待&#34;假\ ntrue \ n&#34;甚至&#34; false \ nfalse \ n&#34;,但我找不到这个实际输出背后的原因。

在这种情况下,这对#defines如何工作?

2 个答案:

答案 0 :(得分:17)

这在[cpp.rescan] / 1-2:

中有描述
  

16.3.4重新扫描和进一步更换

     
      
  1. 替换列表中的所有参数都已被替换并且###处理已完成,所有地标预处理令牌都将被删除。然后重新扫描生成的预处理标记序列以及源文件的所有后续预处理标记,以替换更多的宏名称。
  2.   
  3. 如果在替换列表的扫描期间找到要替换的宏的名称(不包括源文件的其余预处理令牌),则不替换它。 此外,如果任何嵌套替换遇到要替换的宏的名称,则不会替换它。这些未替换的宏名称预处理标记不再可用于进一步替换,即使它们稍后(重新)检查否则宏名称预处理令牌将被替换的上下文。
  4.   

(强调我的)

所以:在代码中遇到TRUE时,它会被FALSE替换。重新扫描序列,FALSE替换为TRUE。重新扫描序列,找到TRUE但不再符合替换条件,因此保留。这同样适用于FALSE(使用交换标识符)的扩展。

答案 1 :(得分:8)

宏无法递归:如果宏直接间接扩展以包含其自己的名称,则第二次出现将不再扩展。因此,在您的情况下,会发生以下扩展:

输入:

cout << TRUE << endl;

TRUE是一个宏,它已经扩展了:

cout << FALSE << endl;

为宏重新扫描扩展文本,找到并展开FALSE

cout << TRUE << endl;

重新扫描扩展文本的宏,找到TRUE;但它已经扩展了一次,所以没有任何反应,它会继续作为TRUE进行后续编译(然后找到全局变量)。