如题。
今天才发现,原来C++从来不检查数组索引是否越界。访问数组元素,比如a[3]
时,编译器其实已经处理成了*(a+3)
,这时候已经没有数组的概念了,检查数组长度就更无从谈起。
这一特性使我遇到了一个非常大的BUG,把它简化成下面的代码:
#include <iostream>
int main() {
double d[3] = {0, 1, 2};
double dd = 9;
d[3] = 0;
std::cout << dd << std::endl;
return 0;
}
输出结果是0而不是9。
也就是说,给d[3]
赋值实际上赋到了dd
头上去了。因为数组d
和变量dd
被依次定义,它们被安排在同一块内存空间的相邻位置,于是d[3]
实际指向的是dd
的内存空间,因此dd
被改写。
在实际编程中,这样的问题很容易出现,但非常难排查。被覆盖的变量可以是基本数据类型,也可以是变量,还可以是指针。而且有时候变量并不一定按照定义时的顺序排列在内存中,编译器完全有可能做了额外的优化,重排这些变量的位置。据说C++是为了提高效率,才弱化了安全保护机制,毕竟两者不可兼得。
编程难,编C++更难,且编且珍惜。