为什么这段代码表现得很奇怪?

Dee*_*tal 0 c++ linux g++

我在C++中有这个代码,它给出了奇怪的输出:

#include<iostream>
using namespace std;
int main(){
    int r[15]={0};
    int n = 5;
    r[15]=20;
    cout<<n;    
}
Run Code Online (Sandbox Code Playgroud)

输出显然应该是5,但它给了我20.现在我知道r [15]超出界限.这个代码应该为尝试访问r [15]抛出异常,不应该吗?但是,它通常用g ++编译并输出错误的输出.我无法弄清楚造成这种异常的原因.有人可以帮忙吗?

仅供参考,这段代码只是一个示例,我不得不从更大的代码中找出这个错误,这花费了我很多时间,否则,如果抛出异常,就可以保存.

更新: 我检查了以下代码:

#include<iostream>
using namespace std;
int main(){
    int n = 5;
    int r[15]={0};
    r[15]=20;
    cout<<n;
}

Output:
20
Run Code Online (Sandbox Code Playgroud)

我也检查了以下代码:

#include<iostream>
using namespace std;
int main(){
    int n = 5;
    int a=5;
    int r[15]={0};
    r[15]=20;
    cout<<n<<endl<<a;
}

Output:
5
5
Run Code Online (Sandbox Code Playgroud)

因此,如果堆栈说明正确,那么在这种情况下,其中任何一个值都应该被修改,对吧?它没有.

cni*_*tar 9

由于r是15个元素的数组,因此r[14]是最后一个元素.因此r[15]=20;是未定义的行为.C++不进行边界检查,因此在处理普通数组时不会出现异常.

在您的情况下,r[15]=20恰好在n存储的精确位置覆盖堆栈.

  • @dpacmittal未定义的行为.请仔细阅读我的答案**."它**会发生**覆盖".无法保证,编译器可以并且将重新排序.跟我说吧:*未定义的行为*. (2认同)

T.J*_*der 5

现在我知道r[15]是出界的.这段代码应该为尝试访问而抛出异常r[15],不应该吗?

除非您使用某种检查库,否则不会.C(和C++)非常接近机器,所以你可以让自己处于这种情况.(这是他们权力的一部分.)在某些编译器上有编译器标志会插入边界检查(以运行时成本),但gcc不执行(您可以找到补丁集将其添加为功能,但我认为仅适用于C).

那里(显然)发生的事情是你的n变量在r数组的15个插槽之后立即在堆栈上结束:

+-------+
| r[0]  |
| r[1]  |
| r[2]  |
...
| r[13] |
| r[14] |
| n     |
+-------+

...所以写入您的越界条目r[15]最终会覆盖它(在您的特定情况下;这不是您可以或应该依赖的行为,堆栈上的事物的顺序未定义为由订单确定它们在源中被声明,并且可能不是).