真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網站制作重慶分公司

C之函數參數(三十九)-創(chuàng)新互聯(lián)

    我們上節(jié)博文講了函數的意義,那么我們今天來講下函數參數。函數參數在本質上與局部變量相同在棧上分配空間,函數參數的初始值是函數調用時的實參值。用下圖來實際說明

為蘆溪等地區(qū)用戶提供了全套網頁設計制作服務,及蘆溪網站建設行業(yè)解決方案。主營業(yè)務為成都網站設計、網站制作、蘆溪網站設計,以傳統(tǒng)方式定制建設網站,并提供域名空間備案等一條龍服務,秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!

C之函數參數(三十九)

        函數參數的求值順序依賴于編譯器的實現(xiàn),我們來看看下面代碼的輸出是什么?為什么呢?

#include 

int func(int i, int j)
{
    printf("i = %d, j = %d\n", i, j);
    
    return 0;
}

int main()
{
    int k = 1;
    
    func(k++, k++);
    
    printf("%d\n", k);
    
    return 0;
}

        我們理論上分析,func 函數先進行 k++,那么 i 就對應為 1,再次進行 k++,對應于 j 為 2。那么第 14 行應打印 i = 1, j = 2,。這時 k 為 3,所以第 16 行打印的值應為 3。我們來看看編譯結果是否如我們所分析的那樣,編譯結果如下

C之函數參數(三十九)

        我們看到 i 和 j 和我們所分析的正好相反,那么這是怎么回事呢?原來在gcc 編譯器中,函數參數的實現(xiàn)是從右向左進行操作的,并非是我們所想的從左向右進行計算的。我們再在 BCC 編譯器中進行編譯,看看結果是怎樣?

C之函數參數(三十九)

        那么我們看到在 BCC 編譯器中也是這樣實現(xiàn)的。函數參數的操作是從右向左的,在現(xiàn)代的編譯器中,基本上是按照從右向左的順序進行函數參數的操作的。在一些古老的編譯器中,也有從左向右的實現(xiàn),這個的實現(xiàn)就依賴于具體的編譯器的實現(xiàn)了。

        下來我們來講一個 C 語言中的知識點:順序點!那么在程序中存在一定的順序點,順序點是指執(zhí)行過程中修改變量值的最晚時刻,在程序到達順序點的時候,之前所做的一切操作必須完成。那么 C 語言中的順序點都在那些時刻呢?a> 每個完整表達式結束時,即分號處;b> &&,||,?: 以及逗號表達式的每個參數計算之后;c> 函數調用時所有實參求值完成后(即進入函數之前);

        下面我們以代碼為例進行分析,代碼如下

#include 

int main()
{
    int k = 2;
    int a = 1;
    
    k = k++ + k++;
    
    printf("k = %d\n", k);
    
    if( a-- && a )
    {
        printf("a = %d\n", a);
    }
    
    return 0;
}

        我們看到第 8 行的進行兩次 k++ 的相加,我們分析結果應該為 5;第 12 行的 a-- 執(zhí)行完之后 a 為 0,但是此時它和 a 相與之后條件仍然為真,所以 第14行應該打印出 a = 0;我么來看看結果是這樣嗎?

C之函數參數(三十九)

        那么我們看到我們分析的第一個是正確的,但是 a = 0 并沒有打印出來,我們再來看看 BCC 編譯器是多少

C之函數參數(三十九)

        我們看到竟然 k = 6,a = 0 依然沒有打印出來。我們再來看看 VS 編譯器

C之函數參數(三十九)

        我們進到反匯編看看它是怎么執(zhí)行的

C之函數參數(三十九)


        我們看到它是這樣執(zhí)行的,先是進行相加操作,這時的++操作被懸掛起來,程序看到;才意識到到了順序點了,所以執(zhí)行完那兩次++操作,所以最后 k 的值為6。我們再來看看第14行怎么執(zhí)行的

C之函數參數(三十九)

        我們看到它是執(zhí)行完 a-- 后看到 && 操作便意識到順序點到了,便返回了。那么這時 a 的值已經變?yōu)?0 了,此時 if 語句條件為假,所以不會執(zhí)行到它里面的打印語句。

        下來我們再來看看參數入棧的順序,函數參數的計算次序是依賴編譯器實現(xiàn)的。那么函數參數的入棧次序是如何確定的呢?這塊就涉及到里一個概念:調用約定。當函數調用發(fā)生時:a> 參數會傳遞給被調用的函數;b> 而返回值會被返回給函數調用者;調用約定描述參數如何傳遞到棧中以及棧的維護方式,參數傳遞順序,調用棧清理。

       調用約定是預定義的可理解為調用協(xié)議,調用約定通常用于庫調用和庫開發(fā)的時候。我們來看看一些常用的操作:a>從右到左依次入棧:__stfcall, __cdecl, __thiscall;b> 從左到右依次入棧:__pascall, __fastcall;那么我們一般的 C 程序開發(fā)遵循的就是上面的 __cdecl 這種方式的。

        那么我們如果要編寫一個計算平均數的函數,我們肯定首先想到的是下面這種

#include 

float average(int array[], int size)
{
    int i = 0;
    float avr = 0;
    
    for(i=0; i

        我們利用一個數組就完成這個功能,那么我們還得去定義一個數組。有什么辦法可以使我們不用定義數組就可以完成這個功能呢?答案就是我們可以利用可變參數的函數來實現(xiàn)這個功能。在 C 語言中可以定義參數可變的函數,參數可變函數的實現(xiàn)依賴于 stdarg.h 頭文件。我們得介紹幾個概念:a> va_list -- 參數集合;b> va_arg -- 取具體參數值;c> va_start -- 標識參數訪問的開始;d> va_end -- 標識參數訪問的結束;

        下來我們來看看可變參數版的程序是怎樣實現(xiàn)的,代碼如下

#include 
#include 

float average(int n, ...)
{
    va_list args;
    int i = 0;
    float sum = 0;
    
    va_start(args, n);
    
    for(i=0; i

        我們在第 6 行定義了 args 參數,在第 10 行開始,14 行進行參數的相加,在 17 行結束。我們來看看第24, 25 行的這樣的定義可行嗎?來看看編譯結果

C之函數參數(三十九)

        結果已經正確實現(xiàn)了,這樣是不是很方便呢?我們可以隨時定義它的大小和內容。那么可變參數也有限制:a> 可變參數必須從頭到尾按照順序逐個訪問;b> 參數列表中至少要存在一個確定的命名參數;c> 可變參數函數無法確定實際存在的參數的數量,同樣也無法確定參數的實際類型,只能我們手動指定;注意:va_arg 中指定了錯誤的類型,那么結果是不可預測的!

        通過對函數參數的學習,總結如下:1、函數的參數在棧上分配空間;2、函數的實參并沒有固定的計算次序;3.順序點是 C 語言中變量修改的最晚時機;4、調用約定指定了函數參數的入棧順序以及棧的清理方式;5、可變參數的函數提供了一種函數設計技巧,提供了一種更方便的函數調用方式;6、可變參數必須順序的訪問,無法直接訪問中間的參數值。

        歡迎大家一起來學習 C 語言,可以加我QQ:243343083。

另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。


網站標題:C之函數參數(三十九)-創(chuàng)新互聯(lián)
URL地址:http://weahome.cn/article/cogppe.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部