通过#define 预处理器指令覆盖 C++ 中的 "endl"
Overriding "endl" in C++ by #define preprocessor directive
我使用以下代码覆盖并替换了 endl
,而不是“换行”。
#include <iostream>
#include <string>
using namespace std;
#define endl "OOOO" //replacing "endl"
int main(){
cout << "start " << endl << " end";
return 0;
}
那么结果就是:
start OOOO end
而不是:
start
end
但是对 cout
做同样的事情会导致错误。
为什么我们可以对 endl
这样做,但我们不能对 cout
这样做?
这当然取决于您将宏定义为什么,以及您如何使用它。预处理后,这个:
#define endl "OOOO"
cout << "start " << endl << " end";
变成这样:
cout << "start " << "OOOO" << " end";
这是一个完全有效的陈述。然而,在预处理之后:
#define cout "OOOO"
cout << "start " << endl << " end";
变成这样:
"OOOO" << "start " << endl << " end";
这不是一个有效的陈述。如果你这样做:
#define printf "OOOO"
cout << printf;
变成这样:
cout << "OOOO";
很好。同样,如果您这样做:
#define cout "OOOO"
printf(cout);
变成这样:
printf("OOOO");
也可以。
你搞乱了编译过程的两个部分。
第一个,解析 #define
是预处理器和简单的文本替换。它不关心你替换了什么,也不知道任何关键字。
第二部分是编译本身,其中实际解释关键字并给出一些"meaning"。
在您的示例中,行
cout << "start " << endl << " end";
变成
cout << "start " << "OOOO" << " end";
完全正确。如果您使用 cout 尝试类似的操作,您可能会得到无效的结果。
要制造更多的混乱,您可以这样做:
#define printf cout
#define if while
#define void int
#define delete(x) x++
int main() {
void i=0;
if(i<5){
printf << i << endl;
delete(i);
}
return 0;
}
会变成
int main() {
int i=0;
while(i<5){
cout<< i << endl;
i++;
}
return 0;
}
在编译器处理之前。
但是,您永远不应该使用宏来更改众所周知的关键字或部分标准库的行为。它会使代码不可读,维护起来很麻烦,并且可能会破坏东西.
为什么我可以写一个#define
宏来代替endl
?
因为你可以为任何东西写一个#define
宏。 #define
宏是在预处理步骤中运行的简单搜索和替换。
为什么我不能写一个 #define
宏来替换 cout
或 printf
?
可以。您可以为任何内容编写 #define
宏。
但是当我为 cout
和 printf
.
编写 #define
宏时,我的代码无法编译
发生这种情况是因为发生宏展开后,您留下了编译错误。
我使用以下代码覆盖并替换了 endl
,而不是“换行”。
#include <iostream>
#include <string>
using namespace std;
#define endl "OOOO" //replacing "endl"
int main(){
cout << "start " << endl << " end";
return 0;
}
那么结果就是:
start OOOO end
而不是:
start
end
但是对 cout
做同样的事情会导致错误。
为什么我们可以对 endl
这样做,但我们不能对 cout
这样做?
这当然取决于您将宏定义为什么,以及您如何使用它。预处理后,这个:
#define endl "OOOO"
cout << "start " << endl << " end";
变成这样:
cout << "start " << "OOOO" << " end";
这是一个完全有效的陈述。然而,在预处理之后:
#define cout "OOOO"
cout << "start " << endl << " end";
变成这样:
"OOOO" << "start " << endl << " end";
这不是一个有效的陈述。如果你这样做:
#define printf "OOOO"
cout << printf;
变成这样:
cout << "OOOO";
很好。同样,如果您这样做:
#define cout "OOOO"
printf(cout);
变成这样:
printf("OOOO");
也可以。
你搞乱了编译过程的两个部分。
第一个,解析 #define
是预处理器和简单的文本替换。它不关心你替换了什么,也不知道任何关键字。
第二部分是编译本身,其中实际解释关键字并给出一些"meaning"。
在您的示例中,行
cout << "start " << endl << " end";
变成
cout << "start " << "OOOO" << " end";
完全正确。如果您使用 cout 尝试类似的操作,您可能会得到无效的结果。
要制造更多的混乱,您可以这样做:
#define printf cout
#define if while
#define void int
#define delete(x) x++
int main() {
void i=0;
if(i<5){
printf << i << endl;
delete(i);
}
return 0;
}
会变成
int main() {
int i=0;
while(i<5){
cout<< i << endl;
i++;
}
return 0;
}
在编译器处理之前。
但是,您永远不应该使用宏来更改众所周知的关键字或部分标准库的行为。它会使代码不可读,维护起来很麻烦,并且可能会破坏东西.
为什么我可以写一个#define
宏来代替endl
?
因为你可以为任何东西写一个#define
宏。 #define
宏是在预处理步骤中运行的简单搜索和替换。
为什么我不能写一个 #define
宏来替换 cout
或 printf
?
可以。您可以为任何内容编写 #define
宏。
但是当我为 cout
和 printf
.
编写 #define
宏时,我的代码无法编译
发生这种情况是因为发生宏展开后,您留下了编译错误。