这是C++中的for循环。我不明白为什么它没有给执行分段错误。为什么这不会产生分段错误
int main()
{
int arr[5];
for (int x = 0; x <= 5; x++)
{
arr[x] = x;
}
return 0;
}
这是C++中的for循环。我不明白为什么它没有给执行分段错误。为什么这不会产生分段错误
int main()
{
int arr[5];
for (int x = 0; x <= 5; x++)
{
arr[x] = x;
}
return 0;
}
这是不确定的行为。未定义行为意味着什么可以发生,包括:
为了更形式化,这是C++ 11 Standard如何定义未定义的行为:
行为这本国际标准中并没有规定要求 [注:当本国际标准省略了 行为的任何明确的定义或当一个程序使用一个错误的结构或错误的数据,可以预期的不确定的行为。 允许不确定的行为 范围从具有不可预知的结果完全无视的情况下,在环境的记录方式特性翻译或 程序执行期间行为(有或没有发行 诊断消息),到终止翻译或执行(发出诊断消息)。许多错误的程序结构不会导致未定义的行为;他们需要被诊断。 末端注]
关于为什么做x[5]
的原因确实是不确定的行为,那是因为x[5]
相当于*(x + 5)
(见第8.3.4/6),和第5.3.1/1关于一元运算符*
规定了:
一元*操作者进行间接:至其所施加应的指针 对象类型,或指向函数类型和结果左值指的是表达对象或功能 表达要点。如果表达式的类型是“指针T,”结果的类型是 “T” [...]
但由于x + 5
不指向任何对象,并且上述段落确实未指定解引用这种指针应的结果,先前引用的句子适用什么:
[...]当本国际标准忽略了行为的任何明确定义未定义行为可预期[...]
Whi ch表示x[5]
是未定义的行为。当用户程序试图做的一个发生
段故障:
那么,你是在实现您的数组中达到出界是正确的,并在最后循环迭代您正在访问你的程序分配的内存之外的东西。它恰好是这样的内存不是系统内存,它存在,所以它可以让你阅读它。
如果你运行这段代码的次数足够多,你最终应该得到一个分段错误,因为它会碰巧放在系统内存或内存末端。
我质疑最后一部分。在我所知道的具有虚拟内存的系统上,这种方式不起作用。每个程序都有自己的地址空间,并且不会干扰除共享内存以外的其他应用程序地址空间。 – drescherjm 2013-05-07 21:03:49
最重要的是arr [5]在栈上。 – drescherjm 2013-05-07 21:05:38
我认为Andy Prowl已经回答说它是未定义的行为。
但是,如果你对它没有崩溃的原因感兴趣,至少在我的编译器中,变量x
被分配到紧跟在数组之后的堆栈中。当您将x
指定为arr[5]
时,您实际上只是将x
指定为自己。
显然这可能会因编译器不同而不同。只是觉得你可能有兴趣知道至少一个特定的编译器在做什么。
这是来自Java,Javascript和C#编码的人......为什么会导致错误? – Renan 2013-05-07 20:46:14
'for(int x = 0; x <5; ++ x)'。从零开始。 – gongzhitaao 2013-05-07 20:46:52
@Renan该数组有5个索引为0到4的元素。正在访问索引5。 – 2013-05-07 20:47:18