1
//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;
}

我尝试了许多不同的输入字符串,令我惊讶的是,我得到了奇怪的结果:

案例一:输入字符串:1234,输出:1234(没问题,因为这是预期的行为)

案例二:输入字符串:12345,输出:12345(编译器没有报告错误,但我期待一个错误:数组边界溢出。)

案例三:输入字符串:123456,输出:123456(编译器没有报告错误,但我期待一个错误:数组边界溢出。)

..................................................................

..................................................................

案例六:输入字符串:123456789,输出:123456789(错误:未处理的异常。访问冲突。)

我的疑问是,当我在 SECTION I 中分配的字符数超过其容量时,编译器会报告错误:数组边界溢出。

但是,当我在第 II 部分尝试同样的事情时,我没有收到任何错误。为什么会这样??请注意:我在 Visual Studio 上执行了这个

4

6 回答 6

4
char str[5] = "12345";

这是一个编译时错误。您将长度为 6 的字符串(注意附加的null-termination)分配给大小为 5 的数组。


char str[5];
cin>>str; 

这可能会产生运行时错误。根据您输入的字符串的长度,您提供的缓冲区(大小 5)可能太小(再次注意空终止)。


编译器当然无法在运行时检查您的用户输入。如果幸运的话,Segmentation Faults 会通知您这样的访问冲突。真的,任何事情都可能发生。

对访问冲突抛出异常不是强制性的。为了解决这个问题,您可以自己实现数组边界检查,或者(可能更好)有容器类根据需要调整它们的大小(std::string):

std::string str;
cin >> str;
于 2012-04-24T11:24:44.937 回答
4

您所看到的是未定义的行为。您正在编写超出范围的数组,在这种情况下可能会发生任何事情((包括看到您期望的输出)。

于 2012-04-24T11:26:14.703 回答
3

我尝试了许多不同的输入字符串,令我惊讶的是,我得到了奇怪的结果:

这种现象称为未定义行为(UB)。

一旦您输入的字符数超过char数组可以容纳的字符数,您就会邀请 UB。
有时,它可能会起作用,有时它可能不起作用,它可能会崩溃。简而言之,没有明确的模式。

[旁注:如果编译器允许void main()编译,那么它不符合标准。]

于 2012-04-24T11:25:32.923 回答
2

这是因为在第二种情况下,编译器无法知道。只有在运行时,才会有错误。默认情况下,C / C++ 不提供运行时边界检查,因此无法识别错误,但会“破坏”您的程序。但是,这种中断不必立即出现,但是虽然 str 指向内存中仅保留固定数量的字节的位置,但无论如何您只需写入更多字节。

您的程序的行为将是未定义的。通常,在您的特定情况下,它可能会继续工作,并且您将覆盖其他一些组件的内存。一旦你写了这么多来访问被禁止的内存(或两次释放相同的内存),你的程序就会崩溃。

于 2012-04-24T11:31:04.540 回答
2

char str[5] = "12345"- 在这种情况下,您没有为空终止符留出空间。因此,当应用程序尝试打印时str,只要没有遇到 null,它就会继续运行,最终会踩到被禁止的内存并崩溃。

在这种`cin情况下,cin 操作在字符串的末尾填充了 0,因此这可以防止程序在内存中走得太远。

然而,根据我的经验,当内存溢出违反规则时,事情会变得疯狂,并寻找一个原因,为什么在一种情况下它可以工作,而在另一种情况下它不起作用,不会导致任何地方。由于内存状态不同,同一个应用程序(内存溢出)通常可以在一台 PC 上运行并在另一台 PC 上崩溃。

于 2012-04-24T11:31:52.970 回答
1

因为编译器会进行静态检查。在你的第二部分,尺寸是事先未知的。这取决于您的输入长度。

我可以建议你使用 STL 字符串吗?

于 2012-04-24T11:29:28.113 回答