在下面的代码中,我试图在temp变量中存储索引0处的数组值。在这行代码中:a[i-1]=a[i]-a[i-1];
当i = 0时,[i-1]变为[-1]。
例如,当我输入的内容为:
3 1 2 3
输出:
i:0
a[0]: 1
TEMP: 1
TEMP: 0
TEMP: 0
TEMP: 0
实际发生了什么?请参考编译器的工作进行解释。我知道如果我提出条件if(i!=0) a[i-1]=a[i]-a[i-1];
,代码将正常工作。但我想知道为什么会出现这种情况。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[10],i,n,temp;
cin>>n;
for(i=0;i<n;i++){
cin>>a[i];
if(i==0){
temp=a[i];
cout<<"i: "<<i<<endl;
cout<<"a[0]: "<<a[i]<<endl;
}
cout<<"TEMP: "<<temp<<endl;
a[i-1]=a[i]-a[i-1];
}
cout<<endl<<"TEMP: "<<temp;
}
答案 0 :(得分:1)
- 为什么编译器没有给出任何错误?
醇>
编译器不需要提供任何错误。访问数组越界有未定义的行为。似乎很明显,数组将在运行时被访问超出界限(然后再次,可能不是那么明显,因为程序的作者在运行程序之前没有捕获它),但是它的成本非常高编译器检查执行路径以搜索一般的错误。
- 为什么临时变量的值会受到影响并在第一次迭代后变为零,尽管只有当i = 0且其他地方没有使用temp时才会为其分配值?
醇>
因为程序的行为未定义。
当允许程序以任何可能的方式运行时,分析为什么程序以某种方式运行通常是没有意义的。但是,这种情况似乎最有可能:当你写出界限时,你会覆盖一些不属于数组的内存。其他变量可能位于不属于数组的内存中。因此,覆盖一些不属于数组的内存可能会破坏某些其他变量的值。这就是你观察到的。
答案 1 :(得分:0)
- 为什么编译器没有给出任何错误?
醇>
正如@ user2079303已经提到的,编译器找到这样的错误太困难了。有单独的工具可以找到更复杂的错误 - 静态和动态代码分析器。例如,如果您使用VS 2015中的默认静态代码分析器,则会发出以下警告:
Severity Code Description
Warning C4701 potentially uninitialized local variable 'temp' used
Warning C6385 Reading invalid data from 'a': the readable size is '40' bytes, but '-4' bytes may be read.
Warning C6386 Buffer overrun while writing to 'a': the writable size is '40' bytes, but '-4' bytes might be written.
Warning C6001 Using uninitialized memory 'temp'.
如果您想为项目提供额外的安全性,请考虑启用所有(或几乎所有)可用警告并定期运行代码分析。