我不明白我的编译器如何获得此输出

时间:2019-10-12 16:13:47

标签: c++ turbo-c++

请注意,我使用的是Turbo C ++编译器,因为我们应该只为学校教学大纲学习Turbo C ++。这就是为什么cout语句在这种情况下从右到左求值的原因。

程序

#include <iostream.h>
#include <string.h>

void func(char *s, char t[]) {
    strcpy(t, "Have fun");
    s = "Be\0Cool";
    cout << s[0] << ++s << s++ << --s << strupr(s+2) << ++s << s++ << s;
}

int main() {
    char x[] = "Hello World!!!", y[] = "Hello World";
    func(x, y);
    cout << x << y;
    return 0;
}

输出

  

CCOOLeeOOLBeBeHello World !!!玩得开心


我觉得输出应该是:

  

C eeOOLBeBeHello World!玩得开心

由于在++s语句的cout部分(第二位置)中,指针位于字符串s的索引 3 ,所以只有'酷”应打印。而是打印“ COOL”。为什么会这样?

1 个答案:

答案 0 :(得分:1)

使用Visual Studio 2019进行测试

出于比较目的,在Visual Studio 2019(DEBUG)中,如果进行必要的更改以编译代码,则程序会崩溃,因为我们尝试修改常量字符串("Be\0Cool")。

如果我们进行其他更改以避免崩溃(通过使用本地数组),则输出为:

  

CCoOLeCoOLOLCoOLBeCoOLHello World !!!玩得开心

如果我们将cout << s[]…;行分割成多个对cout的调用(每个<<之前的一个),则输出将是:

  

BeeeCOOLCOOLHello World !!!玩得开心

或者,如果我们在每个输出之后添加一行,则会得到:

B
e
e
e
COOL


COOL
Hello World!!!
Have fun

试图了解Turbo C ++的输出

如果我们随后将每次对cout的调用都颠倒为从最后一个(即cout << s<< endl;)开始到第一个(cout << s[0] << endl)结束,那么我们得到:

Be
Be

OOL
e
e
COOL
C
Hello World!!!
Have fun

如果我们手动将其写在最后三行,第二行和最后两行之间,且没有空格,则得到:

  

CCOOLeeOOLBeBeHello World !!!玩得开心

这正是您得到的输出。

因此,似乎Turbo C ++从右到左评估了每个表达式。

有关编译(和运行)所需更改的说明

  • <iostream.h>不可用,所以我不得不使用<iostream>
  • #define _CRT_SECURE_NO_WARNINGS必须添加在顶部,因为某些功能不安全(默认情况下不会编译)。
  • using namespace std;以避免对代码进行更多更改。
  • s = (char *)"Be\0Cool";中添加强制转换,以便编译该行。
    • 这会导致崩溃,因为数据是不变的,我们会尝试对其进行修改。
  • 删除演员表,改写char data[] = "Be\0Cool"; s = data;
    • 程序正在运行,但输出为CCoOLeCoOLOLCoOLBeCoOLHello World!!!Have fun
    • 实际上,这是未定义的行为。恰好是实际输出。

未定义的行为

有些东西不是标准定义的,因此不需要以某种方式工作。好吧,正如预期的那样,如果不支持只读内存,它的工作方式类似于读写内存。

对于评估顺序,常见的可能性是:

  • 从左到右
  • 从右到左
  • 什么是最佳选择

此外,由于变量被多次修改,因此在评估期间及之后均未定义s的值。容易记住的规则是避免在单个表达式中多次修改同一变量。

关于strupr

该函数将字符串修改为终止的空字符。对于您而言,它将在调用时将s值中的每个字母都转换为大写。