//SECTION I:
void main()
{
char str[5] = "12345"; //---a)
char str[5] = "1234"; //---b)
cout<<"String is: "<<str<<endl;
}
Output: a) Error: Array bounds Overflow.
b) 1234
//SECTION II:
void main()
{
char str[5];
cout<<"Enter String: ";
cin>>str;
cout<<"String is: "<<str<<endl;
}
我尝试了许多不同的输入字符串,令我惊讶的是,我得到了奇怪的结果:
案例I:输入字符串:1234,输出:1234(没问题,因为这是预期的行为)
案例II:输入字符串:12345,输出:12345(编译器报告没有错误但是我期待错误:数组边界溢出。)
案例III:输入字符串:123456,输出:123456(编译器报告没有错误但是我期待错误:数组边界溢出。)
............................................... ..
............................................... ..
案例VI:输入字符串:123456789,输出:123456789(错误:unhandeled exception.Access Violation。)
我的疑问是,当我在第一部分中分配的字符多于其容量时,编译器报告了ERROR:数组边界溢出。
但是,当我在第二部分尝试同样的事情时,我并没有发现任何错误。为什么会这样?请注意:我在Visual Studio上执行了此操作
答案 0 :(得分:4)
char str[5] = "12345";
这是一个编译时错误。您将长度为6的字符串(请注意附加的null-termination)分配给大小为5的数组。
char str[5];
cin>>str;
这可能会产生运行时错误。根据您输入的字符串的长度,您提供的缓冲区(大小为5)可能太小(再次注意空终止)。
编译器当然无法在运行时检查用户输入。如果幸运的话,分段错误会通知您这样的访问冲突。确实,任何事情都可能发生。
违反访问权限的抛出异常不是强制性的。要解决这个问题,你可以自己实现数组边界检查,或者(可能更好)有容器类根据需要调整它们的大小(std::string
):
std::string str;
cin >> str;
答案 1 :(得分:4)
您所看到的是未定义的行为。你正在编写数组越界,在这种情况下可能发生任何事情((包括看到你期望的输出)。
答案 2 :(得分:3)
我尝试了许多不同的输入字符串,令我惊讶的是,我得到了 奇怪的结果:
这种现象称为未定义行为(UB)。
只要您输入的字符数超过char
阵列所能容纳的字符数,您就会邀请UB
有时,它可能会工作,它可能无法工作,它可能会崩溃。简而言之,没有明确的模式。
[旁注:如果编译器允许编译void main()
,那么它不符合标准。]
答案 3 :(得分:2)
这是因为在第二种情况下,编译器无法知道。只有在运行时,才会出现错误。默认情况下,C / C ++不提供运行时边界检查,因此无法识别错误,但会“中断”程序。但是,这种中断不必立即显示,但是当str指向内存中仅保留固定字节数的位置时,您只需编写更多字节。
您的计划的行为将是未定义的。通常,在您的特定情况下,它可能会继续工作,您将覆盖其他组件的一些记忆。一旦你写了很多东西来访问禁止的内存(或两次释放相同的内存),你的程序就会崩溃。
答案 4 :(得分:2)
char str[5] = "12345"
- 在这种情况下,您没有为空终结符留出空间。因此,当应用程序尝试打印str
时,只要没有遇到null,它就会一直打开,最终踩到伪造的内存并崩溃。
在`cin
情况下,cin操作在字符串末尾填充0,因此这会阻止程序在内存中走得太远。
然而,根据我的经验,当内存超支违反规则时,事情会变得疯狂,并且寻找一个原因,在一个案例中它起作用,而在另一个案例中它不起作用,并不会带来任何结果。通常情况下,由于内存状态不同,同一个应用程序(内存溢出)可以在一台PC上运行并在另一台PC上崩溃。
答案 5 :(得分:1)
因为编译器进行静态检查。在您的第II部分,尺寸未知。这取决于您的输入长度。
我建议您使用STL字符串吗?