zoukankan      html  css  js  c++  java
  • 理解指针

    如题:理解指针  转载请保留作者和地址 http://www.cnblogs.com/scotth/p/3703616.html

    VS如何看汇编代码(DEBUG状态)

      Debug->Windows->DisAssambly即可看到汇编窗口

    先看看C++代码

        BYTE data[1024] = { 1,2,3 };
        BYTE* pdata(data);
        BYTE** ppdata(&pdata);
        *ppdata[0] = '5';

    int _tmain(int argc, _TCHAR* argv[])
    {
        /*
        char temp[100] = "c:abccdcde 
    ";
        char temp2[100] = "c:/abc/bcd/cde 
    ";
        char temp3[100] = "c:\abc\bcd\cde 
    ";
        */
    
        //&取地址   运算符:取出内存地址
        //*间接寻址 运算符:得到内存地址里面的值
    
        int ival = 100; //地址为0x00adf75c{100}
        int *p = &ival;    //取ival的地址  赋给p的指针(地址0x00adf75c 赋给*p)
        ival = 200;        //改ival的值0x00adf75c{200}
    
    
        //printf("
     ival = %d, &ival = 0x%x, *p =0x%x ", ival, &ival, *p);
    
        //little endian
        int **b = &p;//b是二级指针,     第一个指针地址是0x00adf75c{200}(0x00adf75c存的值为200),   第二个指针地址是0x00adf750
        //printf("
     b>>>>>>>>> **b =0x%d, *b=0x%x,  b =%x", **b, *b, b);
    
    
        //============================================================================
        //通过debug可以看到二级指针的信息    0x00adf750{0x00adf75c{200}}
    
    
        int *first = &(**b);
        //1.按照()优先级, 二级指针b  先间接寻址,再间接寻址 得到200的值, 然后取地址  得到ival的地址(也就是*p的值  0x00adf75c{200})
        
        //汇编过程
        //1.  【二级指针b】把0x00adf750 赋给eax
        //2.  eax(间接寻址后)得到 0x00adf75c{200} 赋给ebx,   再取地址  赋给 *first(first指针地址 为0x00adf75c{200})
        
        
        int *second = *b;    
        //二级指针b先把0x00adf750{0x00adf75c{200}}   赋给 寄存器eax, 
        //eax 0x00adf750(间接寻址后)得到0x00adf75c{200}  赋给 *second(second指针地址 为0x00adf75c{200})
    
        int **c = b;//二级指针 b 赋给二级指针c
        //printf("
     c >>>>>>>>>>>> **c =0x%d, *c=0x%d,  c =%d", **c, *c, c);
    
    
        int d = **b;//二级指针b , 间接寻址 再间接寻址(也就是ival指针地址的值),赋给d
    
        return 0;
    }
    View Code

    再看看汇编是如何实现的

    int _tmain(int argc, _TCHAR* argv[])
    {
    00E213B0  push        ebp  
    00E213B1  mov         ebp,esp  
    00E213B3  sub         esp,118h  
    00E213B9  push        ebx  
    00E213BA  push        esi  
    00E213BB  push        edi  
    00E213BC  lea         edi,[ebp-118h]  
    00E213C2  mov         ecx,46h  
    00E213C7  mov         eax,0CCCCCCCCh  
    00E213CC  rep stos    dword ptr es:[edi]  
    00E213CE  mov         eax,dword ptr ds:[00E28000h]  
    00E213D3  xor         eax,ebp  
    00E213D5  mov         dword ptr [ebp-4],eax  
        /*
        char temp[100] = "c:abccdcde 
    ";
        char temp2[100] = "c:/abc/bcd/cde 
    ";
        char temp3[100] = "c:\abc\bcd\cde 
    ";
        */
    
        //&取地址   运算符:取出内存地址
        //*间接寻址 运算符:得到内存地址里面的值
    
        int ival = 100; //地址为0x00adf75c{100}
    00E213D8  mov         dword ptr [ival],64h  
        int *p = &ival;    //取ival的地址  赋给p的指针(地址0x00adf75c 赋给*p)
    00E213DF  lea         eax,[ival]  
    00E213E2  mov         dword ptr [p],eax  
        ival = 200;        //改ival的值0x00adf75c{200}
    00E213E5  mov         dword ptr [ival],0C8h  
    
    
        //printf("
     ival = %d, &ival = 0x%x, *p =0x%x ", ival, &ival, *p);
    
        //little endian
        int **b = &p;//b是二级指针,     第一个指针地址是0x00adf75c{200}(0x00adf75c存的值为200),   第二个指针地址是0x00adf750
    00E213EC  lea         eax,[p]  
    00E213EF  mov         dword ptr [b],eax  
        //printf("
     b>>>>>>>>> **b =0x%d, *b=0x%x,  b =%x", **b, *b, b);
    
    
        //============================================================================
        //通过debug可以看到二级指针的信息    0x00adf750{0x00adf75c{200}}
    
    
        int *first = &(**b);
    00E213F2  mov         eax,dword ptr [b]  
    00E213F5  mov         ecx,dword ptr [eax]  
    00E213F7  mov         dword ptr [first],ecx  
        //1.按照()优先级, 二级指针b  先间接寻址,再间接寻址 得到200的值, 然后取地址  得到ival的地址(也就是*p的值  0x00adf75c{200})
        
        //汇编过程
        //1.  【二级指针b】把0x00adf750 赋给eax
        //2.  eax(间接寻址后)得到 0x00adf75c{200} 赋给ebx,   再取地址  赋给 *first(first指针地址 为0x00adf75c{200})
        
        
        int *second = *b;    
    00E213FA  mov         eax,dword ptr [b]  
    00E213FD  mov         ecx,dword ptr [eax]  
    00E213FF  mov         dword ptr [second],ecx  
        //二级指针b先把0x00adf750{0x00adf75c{200}}   赋给 寄存器eax, 
        //eax 0x00adf750(间接寻址后)得到0x00adf75c{200}  赋给 *second(second指针地址 为0x00adf75c{200})
    
        int **c = b;//二级指针 b 赋给二级指针c
    00E21402  mov         eax,dword ptr [b]  
    00E21405  mov         dword ptr [c],eax  
        //printf("
     c >>>>>>>>>>>> **c =0x%d, *c=0x%d,  c =%d", **c, *c, c);
    
    
        int d = **b;//二级指针b , 间接寻址 再间接寻址(也就是ival指针地址的值),赋给d
    00E21408  mov         eax,dword ptr [b]  
    00E2140B  mov         ecx,dword ptr [eax]  
    00E2140D  mov         edx,dword ptr [ecx]  
    00E2140F  mov         dword ptr [d],edx  
    
        return 0;
    00E21412  xor         eax,eax  
    }
    View Code

    图:

    //==========分割线

    有个问题提下:

    为什么【一级指针0x00adf75c】定义早于【二级指针0x00adf750 】但是二级指针的内存地址在低位

    原因:

    机器是intel x64  【little endian机】

    所以每8位,高位地址在前,低位地址在后面,所以先分配0x00adf75c,再分配0x00adf750

    参考 [内存布局](http://www.cnblogs.com/scotth/p/4330649.html)

    大端小端知识传送门(深入理解计算机里面也有讲)

    http://en.wikipedia.org/wiki/Endianness

     //===========================分割线

    有一个指针题,题目如下:

    看输出什么答案+代码。都没什么意义,但是对于理解内存还是可以的。

    int _tmain(int argc, _TCHAR* argv[])
    {
        char* c[] = { "ENTER", "NEW", "POINT", "FIRST" };
        char** cp[] = { c + 3, c + 2, c + 1, c };
        char*** cpp = cp;
        
        printf("%s
    ", cpp[2][1] + 2);
        printf("%s
    ", **++cpp);//注意!!!!这里cpp首地址 向下偏移+1
        printf("%s
    ", *--*++cpp + 3);//
        //先++cpp (地址再偏移+1)
        //间接寻址*,再间接寻址*--,这里相当于cpp[2][0]的--,     cpp[2][0]=new  cpp[2][1]=point  cpp[2][2]=null  cpp[2][3]=null
        //cpp[2][0]=new,基础上-- ,已经没有内容了!!    但是c的内存是连续的,所以还会--, 为enter
        //enter 字符再+3  结果为 er
    
        //偏移后的结果
        printf("%s
    ", cpp[1][3] + 3);
        
        return 0;
    }
    View Code

  • 相关阅读:
    ubuntu18安装net-snmp
    virtual box安装ubuntu系统 ping通 && xshell可以连接
    高中操场所见所思
    如何写好研究生开题报告
    在加州考驾照
    一个软件工程项目竞赛网站
    结对项目总结
    喜马拉雅随车听开通啦
    裘老师赠书
    推荐博客链接
  • 原文地址:https://www.cnblogs.com/scotth/p/3703616.html
Copyright © 2011-2022 走看看