最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言進階可變參數(shù)列表

 更新時間:2022年02月14日 14:39:33   作者:喬喬家的龍龍  
這篇文章主要為大家介紹了C語言進階可變參數(shù)列表的示例詳解有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步

可變參數(shù)

可變參數(shù)是C語言提供的一種參數(shù)可變的機制,咱希望函數(shù)帶有可變數(shù)量的參數(shù),而不是預(yù)定義數(shù)量的參數(shù)。它允許咱定義一個函數(shù),能根據(jù)具體的需求接受可變數(shù)量的參數(shù),比如這種:

int Max(int num,...)
{
 va_list arg;
 va_start(arg,num);
 int max = va_arg(arg,int);
 for(int i = 1;i<num;i++)
 {
 int sid = va_arg(arg,int);
 }
 if(sid > max)
 {
 max = sid;
 }
 va_end(arg);
 return max; 
}
int main()
{
int a = Max(5,1,2,3,4,5);
printf("%d\n",a);
return 0;
}

如上形式Max函數(shù)就用到了可變參數(shù),注意!使用可變參數(shù)時,Max內(nèi)首元素 ‘ 5 ’代表元素個數(shù)

在這里插入圖片描述

那么問題來了,如果函數(shù)沒有形式參數(shù),可以給函數(shù)傳遞嗎?答案是可以的,在C語言中,只要發(fā)生了函數(shù)調(diào)用并調(diào)用了參數(shù),必定會形成臨時變量;所謂臨時拷貝(變量)的本質(zhì),也就是在棧幀內(nèi)部形成的(從右向左形成臨時拷貝(變量)).

宏觀過程

va_list定義了可以訪問可變參數(shù)部分的變量,他的本質(zhì)是一個 char 類型指針。va_start 使 b 指向可變參數(shù)部分,va_end 是用來完成收尾工作的,本質(zhì)就是將參數(shù)arg置為空,避免野指針。

掐頭去尾,我們看看主體部分。首先 arg 指針先讓我的數(shù)據(jù)入棧,我們打開反匯編能看到棧頂 esp 位置,再在內(nèi)存窗口找到 esp 位置,就會看到這個經(jīng)典的一幕,倒著入棧連著幾個數(shù)據(jù)入棧是壓在一起的,這種結(jié)構(gòu)對我們查找元素就非常友好了。

在這里插入圖片描述


宏觀的框架就是我們傳入的變量 num 就代表第一個參數(shù) 5,va_start 就是讓 arg 原本指向5的 ,再讓他指向有效部分,比如 1,根據(jù)指向 1 的起始地址, va_start 指向他的可變部分(去掉已指向的有效部分),具體如何實現(xiàn)見下文;最后 va_arg 就是根據(jù)類型 int ,從起始地址開始連續(xù)讀取找到某一個元素,這樣最終會把所需要的 max 的值讀出來。

原理

可變參數(shù)列表對應(yīng)的函數(shù),最終調(diào)用也是函數(shù)調(diào)用,也要形成棧幀,棧幀形成前,臨時變量會先入棧,根據(jù)咱之前總結(jié)的,參數(shù)位置都是相對固定的;在可變參數(shù)中 ,如果是短整型,一般都要進行整型提升,比如參數(shù)傳入的是 char 類型,但實際傳出的是 int 類型,這就是我們的 va_arg(arg,int)為什么是 int 而不是 char,所以在 va_arg 中指定了錯誤的類型,那結(jié)果無法預(yù)測。

要注意:
1.可變參數(shù)必須從頭到尾逐個進行訪問,如果你訪問了幾個可變參數(shù)后想半途而廢,是可以做到的,但如果一開始就想訪問中間某個元素的話,噠咩!
2.參數(shù)列表中至少有一個命名參數(shù),如果連一個參數(shù)都沒有,就沒辦法使用 va_start;
3.這些宏是沒辦法直接判斷實際存在的參數(shù)數(shù)量的,也無法判斷每個參數(shù)的類型

格局打開

#define _crt_va_start(ap,v)  (ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)
#define _crt_va_arg(ap,t)  (*(t*)((ap += _INTSIZEOF(t) - _INTSIZEOF(t))
#define _crt_va_start(ap)  (ap = (va_list)0)
)

談完原理就要談原理的原理,可變參數(shù)的幾個宏就給出了他的運作原理,ap 就相當于 arg, v 就相當于變量 num,va_list 相當于 char *,這里 ADDRESS 相當于取地址,所以就是在對 char 指針強轉(zhuǎn)之后,此時就有了一個指針以一字節(jié)為單位,指向入棧的第一個有效元素。要想繼續(xù)指向后面可變部分,就要繼續(xù)向下移動四個字節(jié),加上他本身大小就能移動到可變部分。

第二個宏也是特別有意思,ap是va_arg(arg,int),t 是我們的類型—— int ,括號里的部分:(ap += _INTSIZEOF(t))其中 INTSIZEOF 計算了int 的大小,這里讓 ap 先 += 四個字節(jié),就讓 ap 直接指向了下一個元素的位置,后面再減去 int 的大小讓他又回到了第一個元素

在這里插入圖片描述


注意減的過程并沒有賦給 ap,ap指向的是 2,而整個表達式指向的是 4,(t) 將這個 char 類型指針強轉(zhuǎn)成 int 類型指針再解引用,通過強制轉(zhuǎn)換,提取出符合類型大小的數(shù)據(jù)。整個過程就是把第一個元素分離出來了。這個設(shè)計可謂非常優(yōu)秀,不僅指針下移了,元素也訪問了,屬實美哉。

end宏很好理解,ap = 0了再強轉(zhuǎn)成 char* ,他的實際意義就是將指針歸0,避免野指針。

四字節(jié)對齊

INTSIZEOF 是如何實現(xiàn)的?我們將 INTSIZEOF 轉(zhuǎn)到定義,下面這段宏在函數(shù)內(nèi)部就開始進行使用了為什么還要進行四字節(jié)對齊呢?因為從首元素到第二個元素中間的空間是可以訪問的,我不限制大小就有可能訪問不到第二個元素,所以在形參被運用時除了發(fā)生整型提升還有就是四字節(jié)對齊。

#define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1)& ~(sizeof(int) - 1))

比如我是個 char 類型,sizeof(char)+sizeof(4)-1 &~ (sizeof(4)-1)就是 4 &~ 3,0000……0100 & 1111……1100 = 4 , 如此就能實現(xiàn)以最小的方式向上四字節(jié)取整,完成四字節(jié)對齊。從可讀性上講,這是真的麻煩,我們其實直接寫成(n+4-1)& -(4-1)也無妨,這種簡潔版不香嗎是吧。

今天就先到這里,摸了家人們,更多關(guān)于C語言可變參數(shù)列表的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++入門筆記之std::vector容器詳解

    C++入門筆記之std::vector容器詳解

    這篇文章主要給大家介紹了關(guān)于C++之std::vector容器的相關(guān)資料,vector,一種隨機訪問的數(shù)組類型,它提供了對數(shù)組元素的快速、隨機訪問,以及在序列尾部快速、隨機的插入和刪除操作,需要的朋友可以參考下
    2021-07-07
  • EasyC++靜態(tài)持續(xù)變量

    EasyC++靜態(tài)持續(xù)變量

    這篇文章主要介紹了EasyC++靜態(tài)持續(xù)變量,除了自動存儲變量之后,C++當中還有靜態(tài)持續(xù)變量。關(guān)于靜態(tài)持續(xù)變量的定義C++和C語言是一樣的,它擁有三種鏈接性,即外部鏈接性、內(nèi)部連接性和無鏈接性,下面一起進入文章了解更具體內(nèi)容吧
    2021-12-12
  • C++實現(xiàn)藍橋杯競賽題目---搭積木

    C++實現(xiàn)藍橋杯競賽題目---搭積木

    這篇文章主要介紹了C++實現(xiàn)藍橋杯競賽題目---搭積木,本篇文章通過題目分析列舉公式進行分析算法,包含詳細的圖文,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語言中動態(tài)內(nèi)存管理圖文詳解

    C語言中動態(tài)內(nèi)存管理圖文詳解

    在編寫程序時,通常并不知道需要處理的數(shù)據(jù)量,或者難以評估所需處理數(shù)據(jù)量的變動程度,下面這篇文章主要給大家介紹了關(guān)于C語言中動態(tài)內(nèi)存管理的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • vscode 配置 C/C++ 編譯環(huán)境的詳細圖文教程

    vscode 配置 C/C++ 編譯環(huán)境的詳細圖文教程

    這篇文章主要介紹了vscode 配置 C/C++ 編譯環(huán)境的詳細教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05
  • C/C++的浮點數(shù)在內(nèi)存中的存儲方式分析及實例

    C/C++的浮點數(shù)在內(nèi)存中的存儲方式分析及實例

    這篇文章主要介紹了C/C++的浮點數(shù)在內(nèi)存中的存儲方式分析及實例的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • C語言數(shù)據(jù)結(jié)構(gòu)與算法之圖的遍歷(一)

    C語言數(shù)據(jù)結(jié)構(gòu)與算法之圖的遍歷(一)

    這篇文章主要是介紹了利用深度優(yōu)先算法實現(xiàn)圖的遍歷,文中利用圖文詳細的介紹了實現(xiàn)步驟,對我們學習數(shù)據(jù)結(jié)構(gòu)與算法有一定的幫助,需要的朋友可以參考一下
    2021-12-12
  • 詳解C++中的函數(shù)調(diào)用和下標以及成員訪問運算符的重載

    詳解C++中的函數(shù)調(diào)用和下標以及成員訪問運算符的重載

    這篇文章主要介紹了詳解C++中的函數(shù)調(diào)用和下標以及成員訪問運算符,講到了這些二元運算符使用的語法及重載,需要的朋友可以參考下
    2016-01-01
  • C++類成員構(gòu)造函數(shù)和析構(gòu)函數(shù)順序示例詳細講解

    C++類成員構(gòu)造函數(shù)和析構(gòu)函數(shù)順序示例詳細講解

    這篇文章主要介紹了C++類成員構(gòu)造和析構(gòu)順序示例,看了這個例子大家就可以明白c++構(gòu)造析構(gòu)的奧秘
    2013-11-11
  • C++之Primer算術(shù)運算符詳解

    C++之Primer算術(shù)運算符詳解

    這篇文章主要介紹了C++之Primer算術(shù)運算符方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03

最新評論

汶上县| 余江县| 万州区| 泾阳县| 绥滨县| 扎兰屯市| 云和县| 东至县| 浦城县| 库伦旗| 安塞县| 怀远县| 新民市| 东辽县| 敖汉旗| 新乐市| 梁平县| 辰溪县| 盐津县| 岳阳市| 张北县| 河曲县| 滕州市| 化德县| 金山区| 阿荣旗| 环江| 嘉禾县| 彰武县| 罗甸县| 仁怀市| 海门市| 威宁| 清新县| 韶山市| 永登县| 云霄县| 云安县| 麻栗坡县| 壤塘县| 交口县|