C语言可变参数全解
cstdarg(stdarg.h)
可變參數的處理
? ? 這個頭文件定義了一些宏,可以通過這些宏來逐個訪問被調函數的沒有名字的參數列表,這些參數的個數
和類型都是不知道的。
? ? 一個函數可以通過包含一個逗號和三個點(,...)接收可變數量的額外參數,而不需要給出相應的參數定義。
這些可變參數必須出現在常規命名參數的后面。
返回值 函數名 (參數聲明 , ...);
可以通過該頭文件中定義的宏va_start, va_arg和va_end來訪問額外的參數。
*首先,va_start初始化了一個名為va_list的可變參數列表;
*序列的執行va_arg將會按照參數傳遞給函數的順序產生額外參數的值;
*最胡,va_end必須在函數返回之前被執行。
該頭文件包含了一個類型:
va_list 包含可變參數信息的類型。(類型)
三個函數:
va_start ? ? ? ??初始化一個可變參數列表。(宏)
va_arg 獲取下一個參數。 ? ? ? ? ? ? ? ?(宏)
va_end 停止使用可變參數列表。 ? ?(宏)
? ? 一些C編譯器的實現(例如ISO C99兼容的編譯器)同樣也包含一個va_copy宏,用于復制一個va_list對象,
但是這并不是ISO C++標準的一部分。
va_start
void va_start (va_list ap, paramN);
初始化可變參數列表
? ? 初始化最為參數傳入的va_list類型的對象ap,ap保存了通過va_arg獲得參數paramN之后的可變參數的
信息。
? ? 一個函數執行了va_start,就必須在函數返回之前執行va_end。
參數
ap
va_list類型的對象,保存了通過va_arg獲取可變參數的信息。
paramN
函數定義的最后一個命名參數的名字。
返回值
無
<span?style="font-size:16px;">/*?va_start?example?*/?? #include?<stdio.h>?? #include?<stdarg.h>?? ?? void?PrintFloats?(?int?amount,?...)?? {?? ??int?i;?? ??double?val;?? ??printf?("Floats?passed:?");?? ??va_list?vl;?? ??va_start(vl,amount);?? ??for?(i=0;i<amount;i++)?? ??{?? ????val=va_arg(vl,double);?? ????printf?("\t%.2f",val);?? ??}?? ??va_end(vl);?? ??printf?("\n");?? }?? ?? int?main?()?? {?? ??PrintFloats?(3,3.14159,2.71828,1.41421);?? ??return?0;?? }</span>??
這函數PrintFloats以amount作為它的第一個參數,代表額外參數的數量,將會通過cstaarg定義的宏讀取,
并且以一種特殊的格式打印出來。
va_arg
type va_arg ( ?va_list ap, type )
獲取下一個參數
? ? 這個宏展開成了一個表達式,該表達式包含著可變參數列表中下一個參數的類型和值。
? ? 下一次調用這個宏將會展開以同樣順序傳遞給函數的下一個參數。
注意va_arg不能決定傳遞給函數的參數的實際類型,但是可以以宏type的類型作為它的類型。
同樣也需要注意va_arg不能決定此次獲取的參數是否為傳遞給該函數的參數中的最后一個。函數必須如下
來設計:參數的數量必須可以通過已經讀取的命名的或者是沒命名的參數的值來確定。
參數
ap
? ? 一個va_list類型的對象。這個參數在va_arg調用之前,必須通過調用va_start來初始化。
type
? ? 一個類型名。這個類型名就是該宏展開后的表達式的類型(例如,它的返回類型)。一個合法的適合va_arg
使用的類型表達式必須如下:當一個*號添加到它的右邊,那么它的結果表達式必須是一個合法的type類型的
指針。
返回值
以類型type的類型表達式返回下一個額外參數。
示例
[cpp] view plaincopy<span?style="font-size:16px;">/*?va_arg?example?*/?? #include?<stdio.h>?? #include?<stdarg.h>?? ?? ?? int?FindMax?(?int?amount,?...)?? {?? ??int?i,val,greater;?? ??va_list?vl;?? ??va_start(vl,amount);?? ??greater=va_arg(vl,int);?? ??for?(i=1;i<amount;i++)?? ??{?? ????val=va_arg(vl,int);?? ????greater=(greater>val)?greater:val;?? ??}?? ??va_end(vl);?? ??return?greater;?? }?? ?? ?? int?main?()?? {?? ??int?m;?? ??m=?FindMax?(7,702,422,631,834,892,104,772);?? ??printf?("The?greatest?one?is:?%d\n",m);?? ??return?0;?? }</span>??
<span?style="font-size:16px;">/*?va_arg?example?*/?? #include?<stdio.h>?? #include?<stdarg.h>?? ?? void?PrintLines?(?char*?first,?...)?? {?? ??char*?str;?? ??va_list?vl;?? ?? ??str=first;?? ?? ??va_start(vl,first);?? ?? ??do?{?? ????printf?("%s\n",str);?? ????str=va_arg(vl,char*);?? ??}?while?(str!=NULL);?? ?? ??va_end(vl);?? }?? ?? int?main?()?? {?? ??PrintLines?("First","Second","Third","Fourth",NULL);?? ??return?0;?? }</span>??
PrintLines函數使用了可變參數。第一個傳遞的參數是first,但是余下的參數都是在do-while循環中使用
va_arg一次獲得了,該循環在獲取的可變參數為null指針的時候結束。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
可變參數的處理
? ? 這個頭文件定義了一些宏,可以通過這些宏來逐個訪問被調函數的沒有名字的參數列表,這些參數的個數
和類型都是不知道的。
? ? 一個函數可以通過包含一個逗號和三個點(,...)接收可變數量的額外參數,而不需要給出相應的參數定義。
這些可變參數必須出現在常規命名參數的后面。
返回值 函數名 (參數聲明 , ...);
可以通過該頭文件中定義的宏va_start, va_arg和va_end來訪問額外的參數。
*首先,va_start初始化了一個名為va_list的可變參數列表;
*序列的執行va_arg將會按照參數傳遞給函數的順序產生額外參數的值;
*最胡,va_end必須在函數返回之前被執行。
該頭文件包含了一個類型:
va_list 包含可變參數信息的類型。(類型)
三個函數:
va_start ? ? ? ??初始化一個可變參數列表。(宏)
va_arg 獲取下一個參數。 ? ? ? ? ? ? ? ?(宏)
va_end 停止使用可變參數列表。 ? ?(宏)
? ? 一些C編譯器的實現(例如ISO C99兼容的編譯器)同樣也包含一個va_copy宏,用于復制一個va_list對象,
但是這并不是ISO C++標準的一部分。
va_start
void va_start (va_list ap, paramN);
初始化可變參數列表
? ? 初始化最為參數傳入的va_list類型的對象ap,ap保存了通過va_arg獲得參數paramN之后的可變參數的
信息。
? ? 一個函數執行了va_start,就必須在函數返回之前執行va_end。
參數
ap
va_list類型的對象,保存了通過va_arg獲取可變參數的信息。
paramN
函數定義的最后一個命名參數的名字。
返回值
無
示例
[cpp] view plaincopy這函數PrintFloats以amount作為它的第一個參數,代表額外參數的數量,將會通過cstaarg定義的宏讀取,
并且以一種特殊的格式打印出來。
va_arg
type va_arg ( ?va_list ap, type )
獲取下一個參數
? ? 這個宏展開成了一個表達式,該表達式包含著可變參數列表中下一個參數的類型和值。
? ? 下一次調用這個宏將會展開以同樣順序傳遞給函數的下一個參數。
注意va_arg不能決定傳遞給函數的參數的實際類型,但是可以以宏type的類型作為它的類型。
同樣也需要注意va_arg不能決定此次獲取的參數是否為傳遞給該函數的參數中的最后一個。函數必須如下
來設計:參數的數量必須可以通過已經讀取的命名的或者是沒命名的參數的值來確定。
參數
ap
? ? 一個va_list類型的對象。這個參數在va_arg調用之前,必須通過調用va_start來初始化。
type
? ? 一個類型名。這個類型名就是該宏展開后的表達式的類型(例如,它的返回類型)。一個合法的適合va_arg
使用的類型表達式必須如下:當一個*號添加到它的右邊,那么它的結果表達式必須是一個合法的type類型的
指針。
返回值
以類型type的類型表達式返回下一個額外參數。
示例
[cpp] view plaincopy
FindMax函數使用它的第一個參數保存將會獲取到的額外參數的數量。第一個額外的參數被獲取并且作為初始
的比較值,然后在一個循環里獲取余下的參數并且返回其中最大的一個(在這里就是892)。
va_end
void va_end( va_list ap );
? ? 執行合適的動作,使得我們可以從使用了va_list類型對象ap獲取額外參數的函數中正常返回。
? ? 無論va_start在之前的什么時候被執行,這個宏必須在函數返回之前執行。
參數
ap
? ? va_list對象,也就是之前通過va_start初始化的對象。
返回值
無
示例
PrintLines函數使用了可變參數。第一個傳遞的參數是first,但是余下的參數都是在do-while循環中使用
va_arg一次獲得了,該循環在獲取的可變參數為null指針的時候結束。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
- 上一篇: IOS约束三个按钮等宽等高,均分整个vi
- 下一篇: Swift5关于根据一个frame得到最