C語言以數組和結構體傳參__C語言

來源:互聯網
上載者:User

C語言函數調用時的傳參操作在32位x86機器上依賴棧進行.而在x86_64的機器上使用了部分寄存器作為輔助,但如果參數過多,寄存器不夠使用,此時也必須藉助於棧操作實現傳參.儘管C語言對函數傳遞參數的個數沒有明確限制(依編譯器實現而定:http://stackoverflow.com/questions/9034787/function-parameters-max-number),但過多的參數傳遞勢必影響代碼執行效率.

通常C語言函數傳參是非常明確的,如下面這個函數:

int test(int a,float b,int *pointer);
注:以下例子均使用32位x86,gcc編譯器說明.

但如果把數組或結構體作為參數傳遞呢?到底傳遞了多少參數,佔用了多少棧空間?

typedef struct list{    int a;    int b;    int c;    int d;    int e;}list;int test1(int array[5]);int test2(list listtest);

先看數組的例子:
/*passing arguments test:array*/#include<stdio.h>void array(int tmp[5]){        printf("%d\n",tmp[2]);}int main(void){        int test[]={1,2,3,4,5};        array(test);}
編譯成彙編代碼,先截取main函數傳參部分:
        movl    $1, -32(%ebp)        movl    $2, -28(%ebp)        movl    $3, -24(%ebp)        movl    $4, -20(%ebp)        movl    $5, -16(%ebp)        leal    -32(%ebp), %eax        pushl   %eax        call    array
可以看到,在main函數中先將數組元素寫入數組空間內,然後將數組地址(即元素a[0]的地址)儲存在eax中,接著把eax壓棧,最後調用array函數.再看看array函數:

array:.LFB0:        pushl   %ebp        movl    %esp, %ebp        subl    $8, %esp        movl    8(%ebp), %eax        addl    $8, %eax        movl    (%eax), %eax        subl    $8, %esp        pushl   %eax        pushl   $.LC0        call    printf        addl    $16, %esp        nop        leave        ret

首先是老套的操作:儲存ebp,同步ebp和esp,esp向下移動,以建立新函數棧環境.然後取8(%ebp).what is it?其實函數執行到這裡經過了3次壓棧:pushl %eax,call array,pushl %ebp.而每一次壓棧都是32位,也就是4個位元組.所以0(%ebp)是pushl %ebp的值,4(%ebp)是函數返回地址,8(%ebp)是pushl %eax的值,即數組地址.當然後面的addl $8,%eax就是tmp[2]的地址了,不再贅述.說了這麼多,總之一句話,array(test)僅僅是傳遞了一個數組地址而已,並沒有把整個數組元素一起作為參數傳給子函數.

再來看結構體的例子:

#include<stdio.h>typedef struct list{        int a;        int b;        int c;        int d;}list;void test(list tmp){        printf("%d\n",tmp.b);}int main(void){        list tmp={.a=10,.b=20,.c=30,.d=40};        test(tmp);}

同樣截取main函數參數傳遞片段:
        movl    $10, -24(%ebp)        movl    $20, -20(%ebp)        movl    $30, -16(%ebp)        movl    $40, -12(%ebp)        pushl   -12(%ebp)        pushl   -16(%ebp)        pushl   -20(%ebp)        pushl   -24(%ebp)        call    test

可以看到,這下是實實在在把結構體中的成員全部壓棧了.因此在開源項目代碼中,常常不會看到以結構體作為參數的,而是傳遞一個指向該結構體的指標.這樣無論結構體有多少成員,壓棧也僅僅壓入一個值了.如下面的代碼:
#include<stdio.h>typedef struct list{        int a;        int b;        int c;        int d;}list;void test(list *tmp){        printf("%d\n",tmp->b);}int main(void){        list tmp={.a=10,.b=20,.c=30,.d=40};        test(&tmp);}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.