在《C陷阱和缺陷》的第三章第六小节中,有以下代码段和描述:
1: int i,a[10];
2: for(i=1;i<=10;i++)
3: a[i]=0;
描述为:以上代码段本意是要设置数组a中所有元素为0,却产生了一个出人意料的“副效果”。for语句的比较部分本来是i<10,却写成了i<=10,因此实际上并不存在的a[10]被设置为0,也就是内存中在数组a之后的一个字word的内存被设置为0。如果编译这段代码的编译器按照内存地址递减的方式来给变量分配内存,那么内存中数组a之后的一个字实际上是分配给了整形变量i。此时,本来循环计数器i的值为10,循环体内将并不存在的a[10]设置为0,实际上却是将计数器i的值设置为0,这就陷入了一个死循环。
看完以上的描述,果断不理解什么是内存地址递减方式和为什么a[10]的值实际上就是整形变量i的值?
测试代码A:[测试编译器为gcc 3.3.1]
1: #include <iostream>
2: using namespace std;
3:
4: int main()
5: {
6: int i,j;
7: cout<<"variable i's and j's address:"<<endl;
8: cout<<&i<<' '<<&j<<endl;
9: return 0;
10: }
测试结果为:
由结果可以看出,先定义的整型变量i的地址要比后定义的整型变量j大4个字节,说明了编译器采用了内存地址递减的方式分配变量内存的。
测试代码B:[测试编译器为gcc 3.3.1]
1: #include <iostream>
2: using namespace std;
3:
4: int main()
5: {
6: int i,a[10];
7:
8: cout<<"variable i's and element of array a's address:"<<endl;
9: cout<<&i<<endl;
10: cout<<&a[0]<<' '<<&a[1]<<' '<<&a[2]<<' '<<&a[3]<<' '<<&a[4]<<endl
11: <<&a[5]<<' '<<&a[6]<<' '<<&a[7]<<' '<<&a[8]<<' '<<&a[9]<<endl;
12:
13: return 0;
14: }
测试结果为:
由结果可以看出,整型变量i和数组a的地址并不相邻,但是变量i的地址还是比数组a的地址大。
如果将测试代码B中的第6行代码中的变量定义换一个位置,改成这样的话[int a[10],i;],而其他不变,编译结果为如下:
由结果可以看出,编译器采用了内存地址递减的方式分配变量的内存。
测试代码C:[测试编译器为gcc 3.3.1]
1: #include <iostream>
2: using namespace std;
3:
4: int main()
5: {
6: int i,a[10];
7:
8: cout<<"variable i's and element of array a's address:"<<endl;
9: cout<<&i<<endl;
10: cout<<&a[0]<<' '<<&a[1]<<' '<<&a[2]<<' '<<&a[3]<<' '<<&a[4]<<endl
11: <<&a[5]<<' '<<&a[6]<<' '<<&a[7]<<' '<<&a[8]<<' '<<&a[9]<<endl;
12: cout<<"element a[10]'s address:"<<endl;
13: cout<<&a[10]<<endl;
14:
15: return 0;
16: }
测试结果为:
由结果显示,变量i和数组a的内存块不相邻,但是a[10]的地址和变量i的地址并不相同。
如果将测试代码B中的第6行代码中的变量定义换一个位置,改成这样的话[int a[10],i;],而其他不变,编译结果为如下:
由结果显示,变量i和数组a的内存块相邻,但是a[10]的地址和变量i的地址并不相同,在《C陷阱和缺陷》的第三章第六小节书中,a[10]的值实际上就是整形变量i的值这个不能成立,也就不能形成死循环的说法。
以上过程及结论是本人的观点,欢迎拍砖!多多交流,多多益善!
参考文献:
1.《C陷阱和缺陷》
2.CSDN博主——门外汉的专栏,《编译器对变量的内存分配方式》,链接地址为:http://blog.csdn.net/birdzb/article/details/1876806