我不明白我的编译器是如何得到这个输出的
I don't understand how my compiler got this output
请注意,我使用的是 Turbo C++ 编译器,因为我们的学校教学大纲应该只学习 Turbo C++。这就是为什么在这种情况下 cout
语句从右到左计算的原因。
计划
#include <iostream.h>
#include <string.h>
void func(char *s, char t[]) {
strcpy(t, "Have fun");
s = "Be[=10=]Cool";
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!!!Have fun
我觉得输出应该是:
CCooleeOOLBeBeHello World!!!Have fun
因为在cout
语句的++s
部分(第二个位置),指针在字符串[=14=的索引3处],所以只应打印 'Cool'。相反 'COOL' 正在打印。为什么会这样?
测试 Visual Studio 2019
为了比较,在 Visual Studio 2019 (DEBUG) 中,如果我们进行必要的更改来编译代码,那么程序会崩溃,因为我们试图修改常量字符串 ("Be[=12=]Cool"
)。
如果我们进行额外的更改以避免崩溃(通过使用本地数组),输出为:
CCoOLeCoOLOLCoOLBeCoOLHello World!!!Have fun
如果我们将 cout << s[]…;
行拆分为对 cout
的多次调用(每个 <<
之前调用一次),那么输出将是:
BeeeCOOLCOOLHello World!!!Have fun
或者如果我们在每个输出后添加一行,我们得到:
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
如果我们手动从倒数第三行开始写,然后按顺序写到最后两行,没有 space,我们得到:
CCOOLeeOOLBeBeHello World!!!Have fun
这正是您得到的输出结果。
因此,Turbo C++ 似乎从右到左计算每个表达式。
有关编译所需更改的说明(和 运行)
<iostream.h>
不可用,所以我必须改用 <iostream>
。
#define _CRT_SECURE_NO_WARNINGS
必须在顶部添加,因为某些功能不安全(默认情况下不会编译)。
using namespace std;
以避免对代码进行更多更改。
- 在
s = (char *)"Be[=22=]Cool";
中添加强制转换,以便编译该行。
- 这会导致崩溃,因为数据是常量,我们会尝试修改它。
- 删除演员表,改写
char data[] = "Be[=23=]Cool"; s = data;
- 程序运行但是输出是
CCoOLeCoOLOLCoOLBeCoOLHello World!!!Have fun
- 事实上,这是未定义的行为。它恰好是实际输出。
未定义的行为
有些东西没有被标准定义,因此不需要以某种方式工作。好吧,如果不支持只读内存,它就像读写内存一样工作。
对于评估顺序,常见的可能性是:
- 从左到右
- 从右到左
- 哪个更优
另外,由于一个变量被修改了不止一次,s 的值在计算期间和之后都没有定义。容易记住的规则是避免在单个表达式中多次修改同一个变量。
关于strupr
该函数将字符串修改为终止空字符。在您的情况下,它会将 s
在调用时具有的任何值的每个字母转换为大写。
请注意,我使用的是 Turbo C++ 编译器,因为我们的学校教学大纲应该只学习 Turbo C++。这就是为什么在这种情况下 cout
语句从右到左计算的原因。
计划
#include <iostream.h>
#include <string.h>
void func(char *s, char t[]) {
strcpy(t, "Have fun");
s = "Be[=10=]Cool";
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!!!Have fun
我觉得输出应该是:
CCooleeOOLBeBeHello World!!!Have fun
因为在cout
语句的++s
部分(第二个位置),指针在字符串[=14=的索引3处],所以只应打印 'Cool'。相反 'COOL' 正在打印。为什么会这样?
测试 Visual Studio 2019
为了比较,在 Visual Studio 2019 (DEBUG) 中,如果我们进行必要的更改来编译代码,那么程序会崩溃,因为我们试图修改常量字符串 ("Be[=12=]Cool"
)。
如果我们进行额外的更改以避免崩溃(通过使用本地数组),输出为:
CCoOLeCoOLOLCoOLBeCoOLHello World!!!Have fun
如果我们将 cout << s[]…;
行拆分为对 cout
的多次调用(每个 <<
之前调用一次),那么输出将是:
BeeeCOOLCOOLHello World!!!Have fun
或者如果我们在每个输出后添加一行,我们得到:
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
如果我们手动从倒数第三行开始写,然后按顺序写到最后两行,没有 space,我们得到:
CCOOLeeOOLBeBeHello World!!!Have fun
这正是您得到的输出结果。
因此,Turbo C++ 似乎从右到左计算每个表达式。
有关编译所需更改的说明(和 运行)
<iostream.h>
不可用,所以我必须改用<iostream>
。#define _CRT_SECURE_NO_WARNINGS
必须在顶部添加,因为某些功能不安全(默认情况下不会编译)。using namespace std;
以避免对代码进行更多更改。- 在
s = (char *)"Be[=22=]Cool";
中添加强制转换,以便编译该行。- 这会导致崩溃,因为数据是常量,我们会尝试修改它。
- 删除演员表,改写
char data[] = "Be[=23=]Cool"; s = data;
- 程序运行但是输出是
CCoOLeCoOLOLCoOLBeCoOLHello World!!!Have fun
- 事实上,这是未定义的行为。它恰好是实际输出。
- 程序运行但是输出是
未定义的行为
有些东西没有被标准定义,因此不需要以某种方式工作。好吧,如果不支持只读内存,它就像读写内存一样工作。
对于评估顺序,常见的可能性是:
- 从左到右
- 从右到左
- 哪个更优
另外,由于一个变量被修改了不止一次,s 的值在计算期间和之后都没有定义。容易记住的规则是避免在单个表达式中多次修改同一个变量。
关于strupr
该函数将字符串修改为终止空字符。在您的情况下,它会将 s
在调用时具有的任何值的每个字母转换为大写。