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

在编译器处理之前。

Try it online

但是,您永远不应该使用宏来更改众所周知的关键字或部分标准库的行为。它会使代码不可读,维护起来很麻烦,并且可能会破坏东西.

为什么我可以写一个#define宏来代替endl

因为你可以为任何东西写一个#define宏。 #define 宏是在预处理步骤中运行的简单搜索和替换。

为什么我不能写一个 #define 宏来替换 coutprintf

可以。您可以为任何内容编写 #define 宏。

但是当我为 coutprintf.

编写 #define 宏时,我的代码无法编译

发生这种情况是因为发生宏展开后,您留下了编译错误。