通过#define预处理程序指令覆盖C ++中的“endl”

时间:2016-02-19 02:37:46

标签: c++ c-preprocessor preprocessor-directive

我使用以下代码覆盖endl除了已经为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

这到底发生了什么?我们为什么要覆盖endl,但在代码中使用coutprintf时我们不能这样做(我们可以在不使用时执行此操作)在代码中)?有什么区别?

3 个答案:

答案 0 :(得分:2)

为什么我可以编写#define宏来替换endl

因为您可以为任何内容编写#define宏。 #define宏是在预处理步骤中运行的简单搜索和替换。

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

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

但是当我为#definecout编写printf个宏时,我的代码无法编译。

这种情况正在发生,因为在宏扩展发生后,您将面临编译错误。

答案 1 :(得分:0)

当然,这取决于您定义宏的方式以及使用方式。预处理后,这个:

#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");

哪个也没关系。

答案 2 :(得分:0)

你搞乱了编译过程的两个部分。

第一个,解析#define是预处理器和简单的文本替换。它不关心你替换什么,也不知道任何关键词。

第二部分是编译本身,其中关键字实际被解释并给出了一些“含义”。

在您的示例中,行

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

但是你永远不应该使用宏来改变众所周知的关键字或标准库部分的行为。它使代码不可读,维护混乱,可能会破坏东西。