有些东西让我烦恼,我真的找不到任何通过互联网的答案(或者至少我不知道如何搜索它)。我一直认为,当将矩阵的大小声明为SIZE时,矩阵的第一个元素是0,最后一个是SIZE-1。但是,在编译时:
#include<cstdio>
#include<cstdlib>
int main()
{
double *r;
r = new double[10];
double dr=0.1;
for(int i=0;i<=10;i++) r[i]=(double)i*dr;
for(int i=0;i<=10;i++) printf("%lf\n",r[i]);
delete [] r; r=0;
return 0;
}
没有通知错误(我已经尝试了3个编译器到目前为止gnu,dev和c-free),即使我运行exe也没有发生错误。结果是:
0.000000
0.100000
0.200000
0.300000
0.400000
0.500000
0.600000
0.700000
0.800000
0.900000
1.000000---> element SIZE, which means 11, while I have declared 10 elements.
所以,问题是:这怎么可能?!?!!? 以下是打印地址时的结果:
006E0F88
006E0F90
006E0F98
006E0FA0
006E0FA8
006E0FB0
006E0FB8
006E0FC0
006E0FC8
006E0FD0
006E0FD8---> 11th element
提前谢谢。
答案 0 :(得分:4)
你是对的,大小为N
的数组的索引范围从0
到N-1
。
您正在通过访问超出其边界的数组来调用未定义的行为。这不是编译错误,但运行此类代码将产生不可预测的结果。
答案 1 :(得分:3)
在C和C ++中,理解“未定义行为”的概念非常重要。
这两种语言的主要假设是程序员没有错误。它们永远不会写入数组,它们永远不会删除一个对象两次,它们永远不会对有符号整数进行计算以溢出等等。
这意味着允许编译器和标准库生成的代码忽略这种可能性,无论发生什么事情都会发生。
可能是你的代码在做坏事时会得到段错(即操作系统本身会阻止无意义的操作),但这只有在你运气好的时候才会发生。在大多数情况下,没有任何事情发生更好地说没有什么明显的发生......但是之后的一百万个执行指令可能是一些完全有效的代码会疯狂地表现。
在C和C ++中,触发段错误的代码只是很久以前发生的一些错误的无辜受害者。
因此,在使用C和C ++进行编码时,请记住永远不要犯错误; - )
答案 2 :(得分:0)
从0
到<=10
的循环将访问/打印11个元素。
这是UB。超出数组边界的是UB。
这应修复您的代码:
#include<cstdio>
#include<cstdlib>
int main()
{
double *r;
r = new double[10];
double dr=0.1;
for(int i=0;i<10;i++) r[i]=(double)i*dr;
for(int i=0;i<10;i++) printf("%lf\n",r[i]);
delete [] r; r=0;
return 0;
}
您的代码没有语法错误且没有未解析的引用,因此编译器将信任程序员并让此UB通过。 LINT
工具可能会抓住这个错误,不确定。