zoukankan      html  css  js  c++  java
  • 汇编的艺术(02)& operator

    首先看一段代码:

    void calc(int &a)
    {
        a += 10;
    }
    
    int main()
    {
        int a = 0;
        calc(a);
        printf("%d\n", a);
        return 0;
    }

    答案输出 a = 10 以前有种疑惑,为什么没有把a的地址传进去,也能够改变a的值。

    事实上,这些工作都交给编译器做了,下面看反汇编代码:

    void calc(int &a)
    {
        a += 10;
    00000000  push        ebp  
    00000001  mov         ebp,esp 
    00000003  push        eax  
    00000004  mov         dword ptr [ebp-4],ecx 
    00000007  cmp         dword ptr ds:[00342E14h],0 
    0000000e  je          00000015 
    00000010  call        72393B89 
    00000015  mov         eax,dword ptr [ebp-4] 
    00000018  add         dword ptr [eax],0Ah 
    }
    0000001b  nop              
    0000001c  mov         esp,ebp 
    0000001e  pop         ebp  
    0000001f  ret  
    
    int main()
    {
        int a = 0;
    00000000  push        ebp  
    00000001  mov         ebp,esp 
    00000003  sub         esp,8 
    00000006  cmp         dword ptr ds:[00342E14h],0 
    0000000d  je          00000014 
    0000000f  call        72393BE9 
    00000014  xor         edx,edx 
    00000016  mov         dword ptr [ebp-4],edx 
    00000019  xor         edx,edx 
    0000001b  mov         dword ptr [ebp-4],edx 
    0000001e  xor         edx,edx 
    00000020  mov         dword ptr [ebp-8],edx 
        calc(a);
    00000023  lea         ecx,[ebp-8] 
    00000026  call        dword ptr ds:[003435F8h] 

    注意几行红色的汇编代码,编译器对calc(a)进行的一定程度上的优化,把a的地址直接传给ecx,然后再利用这个地址对a进行操作。

    其实到这里问题就明朗了:int &a = b; a是b的一个引用,a就是b,只不过换了一个马甲而已。

    所以:引用总是指向一个是实例化的对象,这点和指针还是有点差别的,比如下面的代码:

    int main()
    {
        char a = 1;
        char &b = a;
        char* p = &a;
        b += 1;
        printf("%d %d\n", sizeof(b), sizeof(p));
        return 0;
    }

    先思考,b这个引用在栈中是否开辟了空间呢?如果开辟了栈空间给b,那么b和p又有什么样的区别呢?

    int main()
    {
        char a = 1;
    00000000  push        ebp  
    00000001  mov         ebp,esp 
    00000003  sub         esp,10h 
    00000006  cmp         dword ptr ds:[00352E14h],0 
    0000000d  je          00000014 
    0000000f  call        72513BE9 
    00000014  xor         edx,edx 
    00000016  mov         dword ptr [ebp-4],edx 
    00000019  xor         edx,edx 
    0000001b  mov         dword ptr [ebp-8],edx 
    0000001e  xor         edx,edx 
    00000020  mov         dword ptr [ebp-0Ch],edx 
    00000023  xor         edx,edx 
    00000025  mov         dword ptr [ebp-4],edx 
    00000028  mov         dword ptr [ebp-10h],1 
        char &b = a;
    0000002f  lea         eax,[ebp-10h] 
    00000032  mov         dword ptr [ebp-8],eax 
        char* p = &a;
    00000035  lea         eax,[ebp-10h] 
    00000038  mov         dword ptr [ebp-0Ch],eax 
        b += 1;
    0000003b  mov         eax,dword ptr [ebp-8] 
    0000003e  inc         byte ptr [eax] 
        printf("%d %d\n", sizeof(b), sizeof(p));
    00000040  push        0B94194h 
    00000045  push        1    
    00000047  push        4    
    00000049  push        2C4D00h 
    0000004e  call        FFDC31C4 
    00000053  add         esp,10h 
    00000056  nop              
        return 0;

    通过上面的反汇编代码,可以观察出来,b和p在堆栈中是没有本质区别的 char &b = a, char *p = &a的反汇编代码是一样的。

    并且,b和p是一样的在栈中开辟了空间。但是用sizeof(b)和sizeof(p)区别就出来了,一个是字节大小,一个是指针大小。

    通过上面其实也可以得出结论,引用的操作都是由编译器来完成的,引用只不过是实体变量的一个马甲而已。

    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    008 第八篇:爬虫实战(数据可视化之pyecharts)
    案例一 微信聊天机器人
    008 第八篇:爬虫实战
    007 第七篇:分布式爬虫
    006 第六篇:Scrapy框架
    005 第五篇:爬虫高性能相关
    004001 第四篇:存储库简单版之mongodb,redis,mysql
    003 第三篇:解析库之re、beautifulsoup、pyquery
    002 第二篇:请求库之requests,selenium
    001 第一篇:爬虫基本原理
  • 原文地址:https://www.cnblogs.com/kedebug/p/2812797.html
Copyright © 2011-2022 走看看