我正在学习C++,我发现了一个我不理解的行为.如果我在C中编写以下程序:
#include <stdio.h>
int main() {
char question[] = "What is your name? ";
char answer[2];
printf(question);
scanf("%ls", answer);
printf("%s\n", answer);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我输入一个超过两个字节的名字时,答案就是胡言乱语,但即使我不确切知道原因,我也知道出了问题,它试图恢复.
相反,如果我编写这个C++程序(有点等同于前者):
#include <iostream>
using namespace std;
int main() {
char question[] = "What is your name? ";
char answer[2];
cout << question;
cin >> answer;
cout << answer << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我期待类似的行为,因为我声明answer为char数组而不是字符串(可以动态调整其大小).但是当我输入很长的东西时,它会在我输入时打印出来.一个例子:
$ ./test
What is your name? asdfa
asdfa
$ ./test
What is your name? sdhjklwertiuoxcvbnm
sdhjklwertiuoxcvbnm
Run Code Online (Sandbox Code Playgroud)
那么,这里发生了什么?作为第二个问题,当我输入更长的东西时,C中会发生什么?
编辑:只是为了澄清,我知道我可以使用std::string而不是char数组(我已经在上面写了^^).我有兴趣知道程序为何表现出这种行为.现在我知道它是未定义的行为.另外,我纠正了C程序(scanf)中的错误.
Rak*_*kib 12
char answer[2];表示您的数组只能包含2个字符.如果你超过这个,那么内存就会溢出并且是未定义的行为.在数组中保留足够的空间,或者std::string如果使用数组不是必需的,则更好地使用.正如另一个答案指出的那样,你正在以错误的方式接受输入.
这是未定义的行为(UB):
scanf(answer);
Run Code Online (Sandbox Code Playgroud)
scanf函数会将未初始化的内容解释answer为格式字符串,从而导致UB.
它应该是这样的:
scanf("%1s", answer);
Run Code Online (Sandbox Code Playgroud)
请注意,当您声明大小为2的字符数组时,这意味着它可以适合长度最多为1的C字符串,因为您需要一个字符用于null终止符.
请注意,当您在C++程序中为名称输入两个以上的字符时,您也会得到未定义的行为:写入数组的末尾是UB.幸运的是,很少需要在C++中将字符串读入字符数组,因为标准C++库提供了动态调整大小的类std::string,这是表示字符串的更好选择.
你不能指望类似的行为.
在这两种情况下都可以预期未定义的行为:超出内存缓冲区是两种语言中未定义的行为,因此绝对允许任何事情发生.
| 归档时间: |
|
| 查看次数: |
282 次 |
| 最近记录: |