• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • return X++的實現

    發表于:2007-05-25來源:作者:點擊數: 標簽:X++Return相信很多C++
    相信很多學C/C++語言的兄弟并沒有搞清象return X++這樣的語句是怎么實現的。 如果你也像我一樣,眼睛里容不得半點沙,那么,這篇文章就是為你所寫的。 相信很多學C/C++語言的兄弟并沒有搞清象return X++這樣的語句是怎么實現的。 如果你也像我一樣,眼睛里容
    相信很多學C/C++語言的兄弟并沒有搞清象return X++這樣的語句是怎么實現的。
    如果你也像我一樣,眼睛里容不得半點沙,那么,這篇文章就是為你所寫的。

    相信很多學C/C++語言的兄弟并沒有搞清象return X++這樣的語句是怎么實現的。
    如果你也像我一樣,眼睛里容不得半點沙,那么,這篇文章就是為你所寫的。

    情況一:X是一簡單類型
    文件t.c內容如下:
    int f(int a)
    {
    return a++;
    }

    int main()
    {
    int v = 1;
    f(v);
    return 0;
    }
    一般情況這種寫法在c語言中其實沒有任何意義,看一下轉化成匯編的結果(用命令gcc -S t.c)
    1 .file "t.c"
    2 .text
    3 .globl f
    4 .type f, @function
    5 f:
    6 pushl %ebp
    7 movl %esp, %ebp
    8 movl 8(%ebp), %eax
    9 incl 8(%ebp)
    10 popl %ebp
    11 ret
    12 .size f, .-f
    13 .globl main
    14 .type main, @function
    15 main:
    16 pushl %ebp
    17 movl %esp, %ebp
    18 subl , %esp
    19 andl $-16, %esp
    20 movl , %eax
    21 addl , %eax
    22 addl , %eax
    23 shrl , %eax
    24 sall , %eax
    25 subl %eax, %esp
    26 movl , -4(%ebp)
    27 movl -4(%ebp), %eax
    28 movl %eax, (%esp)
    29 call f
    30 movl , %eax
    31 leave
    32 ret
    33 .size main, .-main
    34 .ident "GCC: (GNU) 4.0.0 (Gentoo Linux 4.0.0)"
    35 .section .note.GNU-stack,"",@progbits
    我們看函數f的實現。第八行把形參的值賦給寄存器%eax,linux下的AT&T匯編規定%eax中的內容是函數的返回值,這樣就相當于直接把形參的返回了。而第九行的指令根本就沒有作用,因為函數的形參是局部的auto變量,在函數的運行棧上分配空間。這樣,即使在函數f中改變了形參的值,當函數返回后,這次改變就沒有意義了。
    可以看到,如果用-O優化的話,第九行的指令就被優化掉了。
    命令gcc -S -O3 t.c的結果如下
    1 .file "t.c"
    2 .text
    3 .p2align 4,,15
    4 .globl f
    5 .type f, @function
    6 f:
    7 pushl %ebp
    8 movl %esp, %ebp
    9 movl 8(%ebp), %eax
    10 popl %ebp
    11 ret
    12 .size f, .-f
    13 .p2align 4,,15
    14 .globl main
    15 .type main, @function
    16 main:
    17 pushl %ebp
    18 xorl %eax, %eax
    19 movl %esp, %ebp
    20 subl , %esp
    21 andl $-16, %esp
    22 subl , %esp
    23 leave
    24 ret
    25 .size main, .-main
    26 .ident "GCC: (GNU) 4.0.0 (Gentoo Linux 4.0.0)"
    27 .section .note.GNU-stack,"",@progbits
    看到沒有,函數f的核心指令就剩下一條了,剛才的那條沒有用的指令就被優化掉了。
    管中窺豹,可見一斑。我之所以把整個結果再次帖出來,就是為了讓兄弟們看一下,編譯器的優化效果有多么強!原來很煩瑣的指令,一下就變得簡單明了了,優化后程序的執行速度當然就可想而知了:)

    情形二:X是指針類型
    這種情況就比原來要復雜一點點了,源程序改為如下形式:
    #include

    int f(int *a)
    {
    return (*a)++;
    }

    int main()
    {
    int v = 1;
    f(&v);
    return 0;
    }

    $ gcc -S -O3 t.c后的結果為:
    1 .file "t.c"
    2 .text
    3 .p2align 4,,15
    4 .globl f
    5 .type f, @function
    6 f:
    7 pushl %ebp
    8 movl %esp, %ebp
    9 movl 8(%ebp), %edx #取形參,第N個形參在棧上的位置為(N+1)*4+%ebp
    10 movl (%edx), %eax #把形參指向的地址單元的值賦給%eax
    11 leal 1(%eax), %ecx #把%eax中的值加1后賦給%ecx
    12 movl %ecx, (%edx) #運算結果寫回形參指向的單元,即完成了(*a)++
    13 popl %ebp
    14 ret
    15 .size f, .-f
    16 .p2align 4,,15
    17 .globl main
    18 .type main, @function
    19 main:
    20 pushl %ebp
    21 xorl %eax, %eax
    22 movl %esp, %ebp
    23 subl , %esp
    24 andl $-16, %esp
    25 subl , %esp
    26 leave
    27 ret
    28 .size main, .-main
    29 .ident "GCC: (GNU) 4.0.0 (Gentoo Linux 4.0.0)"
    30 .section .note.GNU-stack,"",@progbits

    其實也不是很麻煩。函數f的核心語句只有四條指令,看上面的注釋就行了。
    如果沒有看匯編結果,有的兄弟一定會犯糊涂了:為什么函數返回了還能有效改變變量的值?
    看了匯編就一清二楚了:其實變量的值仍然是在函數體中改變的,只不過返回的值和改變的值沒有什么必然的聯系而已。


    如果不加優化參數,函數f轉化的匯編的結果如下,晦澀多了吧
    5 f:
    6 pushl %ebp
    7 movl %esp, %ebp
    8 movl 8(%ebp), %eax #取形參
    9 movl (%eax), %eax #取形參所指向的地址單元的值
    10 movl %eax, %ecx #保存%eax的副本
    11 leal 1(%eax), %edx #把%eax中的值加1后放入%edx
    12 movl 8(%ebp), %eax #再次取形參,下一步用
    13 movl %edx, (%eax) #把%edx的值存入%eax指向的單元,即完成了(*a)++
    14 movl %ecx, %eax #恢復%eax的值。再次強調,函數的返回值保存在%eax中
    15 popl %ebp
    16 ret

    原文轉自:http://www.kjueaiud.com

    評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>