为什么我可以设置数组范围之外的值?
Why can I set values outside of the array's range?
据我所知,数组只能是固定大小,这是在创建它时定义的(如果您想创建与动态大小类似的东西,请使用向量代替)。
但是,当我尝试在数组外设置值时,我完全能够:
int badNums[5] = {4, 13, 14, 24, 34};
badNums[999] = -127;
std::cout << badNums[999] << std::endl;
// Returns -127
如果我试图访问固定范围之外的数组值,情况就更奇怪了:
std::cout << badNums[997] << std::endl;
// Returns 825245046 (but seems to be randomly chosen every time I run it)
这是怎么回事?
c++不执行边界检查,因为这会减慢速度。它不会阻止你使用数组外的数组下标(甚至是负数!),但是一旦你这样做了,你就会得到未定义的行为。
有时未定义行为似乎工作正常。但是不要被愚弄了,在你看不到的幕后可能会发生不好的事情。对您的示例做如下修改:
int badNums[5] = {4, 13, 14, 24, 34};
int sentinel = 0;
badNums[6] = -127;
std::cout << badNums[6] << sentinel << std::endl;
在许多编译器上,您将看到sentinel
已将值更改为-127,尽管由于这是未定义的行为,因此不能保证。
总之
你正在读取数组后面的内存。只要内存属于你(或进程),那就"完全可以"。
<标题>长(er)回答当你创建一个数组时,你保留了一定的内存空间(在你的例子中是5*sizeof(int)(应该是~40byte))。当您试图访问越界(这是您正在做的事情的最新术语)的数据时,任何事情都可能发生。你很幸运,你正在访问内存,这属于你的进程,否则操作系统应该(也会)杀死你的进程,你会得到一个SEGFAULT。
一定要确保在数组边界内进行读写操作。其他的都可能导致不良的运行时行为。
<标题> 奖金要检查是否越界访问,可以使用valgrind
valgrind ./yourProgram
,然后valgrind将打印每个访问,这是不应该做的
标题>标题>您在内存中为该值设置了一个位置,但是您没有告诉计算机为您的目的保留该位置。它可能被其他进程或您定义的其他变量覆盖。
正如其他人所说,如果内存已经被其他程序保留,也可能出现不可预测的行为。
badNums[997]
与*((badNums)+(997))
相同
您正在尝试访问一些内存,其中内容可能是任何东西。
可以是其他程序使用的旧值,也可以是您的程序使用的值。
这会导致未定义的行为。
- 函数向量_指针有不同的原型,我可以构建一个吗
- 我可以使用 g++ 进行三种比较 (<=>) 吗?
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 我可以信任表示整数的浮点或双精度来保持精度吗
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- 为什么我可以通过引用修改常量返回
- 我可以在 C++ 中的函数体之外进行操作吗?
- 我可以重新分配/覆盖std::字符串吗
- C++-我可以创建另一个类的成员并在构造函数中使用它吗
- 我可以将调用类的"this"传递给 lambda 函数吗?
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 为什么我可以使用比分配的内存更多的内存
- 在一个读写器队列中,我可以用volatile替换原子吗
- 我可以管道到范围 v3 累积吗?
- 为什么我可以在较小的范围内重新定义常量
- 我可以使用基于范围的 for 循环轻松迭代地图的值吗?
- 在C++标准中,我可以在哪里找到对全局范围内调用函数的支持
- 为什么我可以索引到数字超出范围的三维数组中,但仍然可以访问数组中的最后一个数字
- 为什么我可以设置数组范围之外的值?
- 我可以在c++ switch语句中匹配一个范围而不是单个值吗?