zoukankan      html  css  js  c++  java
  • @清晰掉 数组名只是一个符号的论点

    转自 http://blog.csdn.net/yby4769250/article/details/7294718

    近段时间在整理自己大学几年来学习C++的点点滴滴,写这篇文章源于看林锐博士的《高质量C++指南》时,看到文章直接把指针和数组名视为同一东西,原文为“数组名本身就是一个指针,是一个指针常量,即a等价于int * const a,因此你不能试图修改数组名的值”,摘自第三版127页第7.2.1小节。

        自己初学C++时也被数组和指针搞得昏头转向过,通过多方求证和对比实验已把指针和数组弄得稍明白,但是今天又看到一个人说“数组名就是指针”这样的言论,我就有这个想法把自己对指针和数组名的理解写出来,我不敢说我的理解是正确的,但是,至少没那么彻底的祸害人。

       数组名绝对不等于指针,而且不是指针,这是我的观点

    首先看C标准对指针的解释为:指针是一个变量,变量的值是另外一个变量的地址。那么,既然指针是变量,那么指针必然有自己的存储空间,只不过是该存储空间内的值是一个地址值,而不是别的内容。如果按照林博士的观点“数组名就是指针”,想必,数组名也会是一个变量,而且有自己的存储空间?下面上汇编代码反驳之,汇编代码没有骗我们,数组名仅仅是一个符号,不是变量,它没有自己的存储空间,而指针实实在在的是个变量,有自己的空间:

    下面是C++代码:

    #include <iostream>
    using namespace std;
    
    
    int main()
    {
        int i = 10;
        int *pi = &i; //(1)测试指针pi是否有自己的空间
    
    
        int a[2];     //(1)的对比实验,测试数组名是否有自己的空间
        a[0] = 5;
        a[1] = 15;
        
        int *pa = a;  //(2)测试对数组名的引用的寻址方法
        pa = a+1;
    
    
        int j = a[0]; //(3)对比测试对数组名的引用和对指针变量的引用的不同
        int k = *pa;
    
    
        //++a;        //(4)对比测试对指针变量的修改和对数组名的修改的不同
        ++pa;
    
    
        return 0;
    
    
    }

    这段代码的目的是通过4个对比实验逐一证明指针和数组名不是用一个东西,请看下面的汇编代码便可一目了然,每个对比实验的结果都能说名:数组名不是指针,它就是一个符号。

    6:        int i = 10;
    00401048   mov         dword ptr [ebp-4],0Ah    //(1)
    7:        int *pi = &i;
    0040104F   lea         eax,[ebp-4]           
    00401052   mov         dword ptr [ebp-8],eax    //(2)
    8:
    9:        int a[2];    
    10:       a[0] = 5;
    00401055   mov         dword ptr [ebp-10h],5 //(3)
    
    11:       a[1] = 15;
    0040105C   mov         dword ptr [ebp-0Ch],0Fh
    12:
    13:       int *pa = a;  
    00401063   lea         ecx,[ebp-10h]            //(4)
    00401066   mov         dword ptr [ebp-14h],ecx
    14:       pa = a+1;
    00401069   lea         edx,[ebp-0Ch]           //(5)
    0040106C   mov         dword ptr [ebp-14h],edx
    15:
    16:       int j = a[0]; 
    0040106F   mov         eax,dword ptr [ebp-10h]  //(6)
    00401072   mov         dword ptr [ebp-18h],eax
    17:       int k = *pa;
    00401075   mov         ecx,dword ptr [ebp-14h]
    00401078   mov         edx,dword ptr [ecx]
    0040107A   mov         dword ptr [ebp-1Ch],edx
    18:
    19:       //++a;        
    20:       ++pa;
    0040107D   mov         eax,dword ptr [ebp-14h]  //(7)
    00401080   add         eax,4
    00401083   mov         dword ptr [ebp-14h],eax
    21:
    22:       return 0;
    00401086   xor         eax,eax
    23:
    24:   }

    简单学过汇编的人都基本能看懂上面的代码,下面逐一分析(1)-(7)的汇编代码告诉我们的事实:

    (1)、i是个整型变量,可以看出编译器为i分配了空间,地址为ebp-4

    (2)、先lea取i的地址,然后存入到ebp-8的空间中,这就是pi的地址,足矣证明pi是个变量,有自己的空间

    (3)、重点之处,定义了一个数组,但是,汇编代码告诉我们,编译器只给a[0]和a[1]分配了内存空间,a[0]的地址为:ebp-10,a[1]为:ebp-0C,却没有给,数组名a也分配空间,这里起码可以断定数组名a不是一个变量只是个符号

    (4)、从代码lea ecx,[ebp-10h]可以看出,ebp-10是a[0]的地址,对数组名a的引用已经被替换为对数组首元素的地址了

    (5)、a+1的汇编代码也是编程了对ebp-0c地址单元的引用,而这个地址是a[1]的地址,更进一步说明了问题

    (6)、是为了对比,对数组的引用和对指针的引用不同之处,通过下面三行汇编代码可以看出:

    17:       int k = *pa;
    00401075   mov         ecx,dword ptr [ebp-14h]
    00401078   mov         edx,dword ptr [ecx]
    0040107A   mov         dword ptr [ebp-1Ch],edx

    对指针pa的引用是一个间接访问,epb-14h是pa的地址,而mov ecx,dword ptr [ebp-14h]是先取得pa的地址,然后[ecx]取该地址中的内容,并mov到ebp-1c中,改内存就是变量k的内存空间首地址,这样就完成了对pa的引用

    (7)这个是重点分析的地方,很对多人对于数组名就是指针持赞同观点的一个冠冕堂皇的证据是“数组名不能被修改,因为数组名是一个常量指针”,也就是不能执行 a = a+1;这句话对一般,错一半,对的是,数组名确实不能被修改,错的是,不能被修改的原因不是因为数组名是常量指针,而是因为数组名只是一个符号,不是一个变量,因此不能作为一个左值,因此不能被修改,这里又涉及到左值和右值的问题,就不再赘述,网上资料很多。

    通过上述几个对比实验,能够非常清晰的看到,数组名和指针的本质区别:指针是一个变量,有自己对应的存储空间,而数组名仅仅是一个符号,不是变量,因而没有自己对应的存储空间,到此已经可以得出结论,“数组名永远不等于指针”。

    我认为,林博士的意思是说,数组名和指针在参与表达式运算时效果是一样的,但是不能简单粗暴的说两者是相等的

    上述如有错误之处,恳请指出,我必会虚心听取,认真论证修改,以免更多的人困惑

    上述观点有不少不妥之处,讨论在此http://topic.csdn.net/u/20120316/18/f845d4b5-12b2-4467-9946-d31d3c0fd208.html,可自行结合自己的知识进行分析

  • 相关阅读:
    男孩的眼泪
    清冷
    Java随笔
    Java随笔
    skip a transaction in goldengate(跳过一个事务OGG)
    Oracle性能问题一般排查方法
    Oracle GoldenGate(ogg)安装经验大汇总,采坑总结,绝对干货!
    ORACLE 11G 性能诊断优化之ASH实战分析详解
    Oracle SQL性能优化40条 | 收藏了!
    GoldenGate OGG ORACLE数据复制实施方案
  • 原文地址:https://www.cnblogs.com/ysdu/p/4747258.html
Copyright © 2011-2022 走看看