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

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

C之函數(shù)參數(shù)(三十九)

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

在蕪湖縣等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作按需定制,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),成都全網(wǎng)營銷,成都外貿(mào)網(wǎng)站建設(shè),蕪湖縣網(wǎng)站建設(shè)費(fèi)用合理。

C之函數(shù)參數(shù)(三十九)

        函數(shù)參數(shù)的求值順序依賴于編譯器的實(shí)現(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 函數(shù)先進(jìn)行 k++,那么 i 就對(duì)應(yīng)為 1,再次進(jìn)行 k++,對(duì)應(yīng)于 j 為 2。那么第 14 行應(yīng)打印 i = 1, j = 2,。這時(shí) k 為 3,所以第 16 行打印的值應(yīng)為 3。我們來看看編譯結(jié)果是否如我們所分析的那樣,編譯結(jié)果如下

C之函數(shù)參數(shù)(三十九)

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

C之函數(shù)參數(shù)(三十九)

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

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

        下面我們以代碼為例進(jìn)行分析,代碼如下

#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 行的進(jìn)行兩次 k++ 的相加,我們分析結(jié)果應(yīng)該為 5;第 12 行的 a-- 執(zhí)行完之后 a 為 0,但是此時(shí)它和 a 相與之后條件仍然為真,所以 第14行應(yīng)該打印出 a = 0;我么來看看結(jié)果是這樣嗎?

C之函數(shù)參數(shù)(三十九)

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

C之函數(shù)參數(shù)(三十九)

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

C之函數(shù)參數(shù)(三十九)

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

C之函數(shù)參數(shù)(三十九)

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

C之函數(shù)參數(shù)(三十九)

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

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

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

        那么我們?nèi)绻帉懸粋€(gè)計(jì)算平均數(shù)的函數(shù),我們肯定首先想到的是下面這種

#include 

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

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

        下來我們來看看可變參數(shù)版的程序是怎樣實(shí)現(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 參數(shù),在第 10 行開始,14 行進(jìn)行參數(shù)的相加,在 17 行結(jié)束。我們來看看第24, 25 行的這樣的定義可行嗎?來看看編譯結(jié)果

C之函數(shù)參數(shù)(三十九)

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

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

        歡迎大家一起來學(xué)習(xí) C 語言,可以加我QQ:243343083。


新聞標(biāo)題:C之函數(shù)參數(shù)(三十九)
網(wǎng)頁路徑:http://weahome.cn/article/jhoppp.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部