c++ - 越界访问数组不会出错,为什么?

标签 c++ arrays

我在 C++ 程序中赋值超出范围,如下所示:

#include <iostream>
using namespace std;
int main()
{
    int array[2];
    array[0] = 1;
    array[1] = 2;
    array[3] = 3;
    array[4] = 4;
    cout << array[3] << endl;
    cout << array[4] << endl;
    return 0;
}

程序打印 34。这应该是不可能的。我正在使用 g++ 4.3.3

这是编译和运行命令

$ g++ -W -Wall errorRange.cpp -o errorRange
$ ./errorRange
3
4

只有在分配array[3000]=3000时才会出现段错误。

如果 gcc 不检查数组边界,我如何确定我的程序是否正确,因为这可能会导致以后出现一些严重问题?

我将上面的代码替换为

vector<int> vint(2);
vint[0] = 0;
vint[1] = 1;
vint[2] = 2;
vint[5] = 5;
cout << vint[2] << endl;
cout << vint[5] << endl;

并且这个也不会产生错误。

最佳答案

欢迎来到每个 C/C++ 程序员最好的 friend :未定义行为

出于各种原因,语言标准没有指定很多内容。这是其中之一。

一般来说,每当遇到未定义的行为时,任何事情都可能发生。该应用程序可能会崩溃,可能会卡住,可能会弹出您的 CD-ROM 驱动器或让恶魔从您的 Nose 里出来。它可能会格式化您的硬盘或将所有色情内容通过电子邮件发送给您的祖母。

如果您真的很不幸,它甚至可能看起来正常工作。

该语言只是说明如果您访问数组边界内的元素会发生什么。如果你出界会发生什么,这是未定义的。它今天可能在您的编译器上工作,但它不是合法的 C 或 C++,并且不能保证它在您下次运行该程序时仍然可以工作。或者它现在还没有覆盖重要数据,而您只是还没有遇到它将导致的问题。

至于为什么没有边界检查,答案有几个方面:

  • 数组是 C 语言的遗留物。C 数组是你所能得到的最原始的数组。只是具有连续地址的元素序列。没有边界检查,因为它只是暴露原始内存。在 C 语言中实现强大的边界检查机制几乎是不可能的。
  • 在 C++ 中,可以对类类型进行边界检查。但数组仍然是普通的旧 C 兼容数组。这不是一个类。此外,C++ 还建立在另一条规则之上,这使得边界检查变得不理想。 C++ 的指导原则是“不用为不使用的东西付费”。如果您的代码正确,则不需要边界检查,并且您不应该被迫支付运行时边界检查的开销。
  • 因此,C++ 提供了 std::vector 类模板,它允许两者。 operator[] 旨在提高效率。语言标准不要求它执行边界检查(尽管它也不禁止它)。 vector 还具有 at() 成员函数,保证执行边界检查。因此,在 C++ 中,如果使用 vector ,您将获得两全其美的效果。您无需边界检查即可获得类似数组的性能,并且您可以在需要时使用边界检查访问。

关于c++ - 越界访问数组不会出错,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55377092/

相关文章:

c# - 在 C# 中将十进制数组转换为字节数组,反之亦然

c++ - SDL2 : two displays, 两个窗口和全屏模式

c++ - 如何在 C++ 中右移位?

C++ for structure in vectors access index or use reference instead value

c - c != '\n'条件在 "for"循环中的作用是什么(C语言)?

arrays - R在列中搜索信息

c++ - 为什么我在计算 Pascal 三角形的元素时在递归 C 程序中出现堆栈溢出错误?

c++ - 如何从没有虚拟析构函数的类派生?

Java - 从具有两个给定索引的数组返回一个数组

arrays - Zsh:将文件中的行读入数组