fus*_*har 14 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;
}
Run Code Online (Sandbox Code Playgroud)
使用GCC 4.9.2编译,上面的代码输出:
true
false
Run Code Online (Sandbox Code Playgroud)
产量背后的逻辑是什么?我期望"false \ntrue \n"甚至"false \nfalse \n",但我找不到这个实际输出背后的原因.
在这种情况下,这对#defines如何工作?
Win*_*ute 17
这在[cpp.rescan]/1-2中有描述:
16.3.4重新扫描和进一步更换
- 后在替换列表中的所有参数都已经被取代的和
#
和##
处理已经发生,所有placemarker预处理标记将被删除.然后重新扫描生成的预处理标记序列以及源文件的所有后续预处理标记,以替换更多的宏名称.- 如果在替换列表的扫描期间找到要替换的宏的名称(不包括源文件的其余预处理标记),则不会替换它.此外,如果任何嵌套替换遇到要替换的宏的名称,则不会替换它.这些未替换的宏名称预处理令牌不再可用于进一步替换,即使它们稍后(重新)检查在其中否则将替换该宏名称预处理令牌的上下文中.
(强调我的)
所以:TRUE
在代码中遇到的时候,它被替换为FALSE
.重新扫描序列,FALSE
替换为TRUE
.序列被重新扫描,TRUE
被发现但不再符合更换条件,因此保留.这同样适用于FALSE
(使用交换标识符)的扩展.
宏不能递归:如果宏直接间接扩展以包含其自己的名称,则第二次出现将不再扩展.所以在你的情况下,发生以下扩展:
输入:
cout << TRUE << endl;
Run Code Online (Sandbox Code Playgroud)
TRUE
它是一个宏,它扩展了:
cout << FALSE << endl;
Run Code Online (Sandbox Code Playgroud)
FALSE
找到并扩展了为宏重新扫描的扩展文本:
cout << TRUE << endl;
Run Code Online (Sandbox Code Playgroud)
TRUE
找到重新扫描宏的扩展文本; 但它已经扩展了一次,所以没有任何反应,它会继续TRUE
进行后续编译(然后找到全局变量).