zoukankan      html  css  js  c++  java
  • 探讨变量的内存分配方式

           在《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:  }
    测试结果为:
     
      1 
      由结果可以看出,先定义的整型变量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:  }
      测试结果为:
      2
      由结果可以看出,整型变量i和数组a的地址并不相邻,但是变量i的地址还是比数组a的地址大。
      如果将测试代码B中的第6行代码中的变量定义换一个位置,改成这样的话[int a[10],i;],而其他不变,编译结果为如下:
      3
      由结果可以看出,编译器采用了内存地址递减的方式分配变量的内存。
      测试代码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:  }
      测试结果为:
      4 
      由结果显示,变量i和数组a的内存块不相邻,但是a[10]的地址和变量i的地址并不相同。
      如果将测试代码B中的第6行代码中的变量定义换一个位置,改成这样的话[int a[10],i;],而其他不变,编译结果为如下:
      5
      由结果显示,变量i和数组a的内存块相邻,但是a[10]的地址和变量i的地址并不相同,在《C陷阱和缺陷》的第三章第六小节书中,a[10]的值实际上就是整形变量i的值这个不能成立,也就不能形成死循环的说法。
       以上过程及结论是本人的观点,欢迎拍砖!多多交流,多多益善!
      
       参考文献:
       1.《C陷阱和缺陷》
       2.CSDN博主——门外汉的专栏,《编译器对变量的内存分配方式》,链接地址为:http://blog.csdn.net/birdzb/article/details/1876806
     
  • 相关阅读:
    Spark SQL 编程API入门系列之SparkSQL数据源
    [转]Window2008站点安全设置,IIS7/IIS7.5中目录执行权限的设置方法
    [转]c# 对密码执行散列和 salt 运算方法
    [转]C#使用 Salt + Hash 来为密码加密
    [转]webservice 采用SSL实现加密传输
    [转]如何借助 TLS/SSL 确保套接字连接的安全(使用 C#/VB/C++ 和 XAML 的 Windows 应用商店应用)
    [转]网银在线支付接口和应用
    [转]支付宝接口程序、文档及解读(ASP.NET)
    [转]加盐hash保存密码的正确方式
    [转]如何安全的存储密码
  • 原文地址:https://www.cnblogs.com/arthurtang/p/2638275.html
Copyright © 2011-2022 走看看