日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++:函数参数不确定时用cstdarg(stdarg.h)

發布時間:2024/4/11 c/c++ 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++:函数参数不确定时用cstdarg(stdarg.h) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

◎用法:
func( Type para1, Type para2, Type para3, ... )
{
????? /****** Step 1 ******/
????? va_list ap;
????? va_start( ap, para3 ); //一定要“...”之前的那個參數
????
????? /****** Step 2 ******/
????? //此時ap指向第一個可變參數
????? //調用va_arg取得里面的值
????
????? Type xx = va_arg( ap, Type );
????
????? //Type一定要相同,如:
????? //char *p = va_arg( ap, char *);
????? //int i = va_arg( ap, int );

????? //如果有多個參數繼續調用va_arg

????? /****** Step 3 ******/
????? va_end(ap); //For robust!
}

◎研究:
typedef char *??? va_list;

#define va_start _crt_va_start
#define va_arg _crt_va_arg
#define va_end _crt_va_end

#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_end(ap)??????? ( ap = (va_list)0 )
va_list argptr;
C語言的函數是從右向左壓入堆棧的,調用va_start后,
按定義的宏運算,_ADDRESSOF得到v所在的地址,然后這個
地址加上v的大小,則使ap指向第一個可變參數如圖:?????
????
??? 棧底 高地址
??? | .......?????
??? | 函數返回地址
??? | .......??????
??? | 函數最后一個參數
??? | ....???????????????????????
??? | 函數第一個可變參數?????? <--va_start后ap指向
??? | 函數最后一個固定參數
??? | 函數第一個固定參數
??? 棧頂 低地址
?????
????
然后,用va_arg()取得類型t的可變參數值, 先是讓ap指向下一個參數:
ap += _INTSIZEOF(t),然后在減去_INTSIZEOF(t),使得表達式結果為
ap之前的值,即當前需要得到的參數的地址,強制轉換成指向此參數的
類型的指針,然后用*取值

最后,用va_end(ap),給ap初始化,保持健壯性。

?

example:(chenguiming)

#include??? <stdio.h>???
?? #include??? <ctype.h>???
?? #include<stdlib.h>???
?? #include??? <stdarg.h>???
????
?? int??? average(??? int??? first,??? ...??? )????? //變參數函數,C++里也有???
?? {???
???????? int??? count=0,i=first,sum=0;???
???????? va_list??? maker;??????????? //va_list??? 類型數據可以保存函數的所有參數,做為一個列表一樣保存???
???????? va_start(maker,first);??? //設置列表的起始位置???
???????? while(i!=-1)???
???????? {???
???????? sum+=i;???
???????? count++;???
???????? i=va_arg(maker,int);//返回maker列表的當前值,并指向列表的下一個位置???
???????? }???
???????? return??? sum/count;???
??????????
?? }???
????
?? void??? main(void)???
?? {???
?? printf(??? "Average??? is:??? %d\n",??? average(??? 2,??? 3,??? 4,4,??? -1??? )??? );???
?? }???

?

?

Linux下的stdarg.h

#ifndef _STDARG_H
#define _STDARG_H

typedef char *va_list; /* 定義va_list 是一個字符指針類型*/

/* Amount of space required in an argument list for an arg of type TYPE.
TYPE may alternatively be an expression whose type is used. */
/* 下面給出了類型為TYPE 的arg 參數列表所要求的空間容量。
TYPE 也可以是使用該類型的一個表達式 */

// 下面這句定義了取整后的TYPE 類型的字節長度值。是int 長度(4)的倍數。
#define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))

// 下面這個函數(用宏實現)使AP 指向傳給函數的可變參數表的第一個參數。
// 在第一次調用va_arg 或va_end 之前,必須首先調用該函數。
// 17 行上的__builtin_saveregs()是在gcc 的庫程序libgcc2.c 中定義的,用于保存寄存器。
// 它的說明可參見gcc 手冊章節“Target Description Macros”中的
// “Implementing the Varargs Macros”小節。
#ifndef __sparc__
#define va_start(AP, LASTARG) \
(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#else
#define va_start(AP, LASTARG) \
(__builtin_saveregs (), \
AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#endif

// 下面該宏用于被調用函數完成一次正常返回。va_end 可以修改AP 使其在重新調用
// va_start 之前不能被使用。va_end 必須在va_arg 讀完所有的參數后再被調用。
void va_end (va_list); /* Defined in gnulib *//* 在gnulib 中定義 */
#define va_end(AP)

// 下面該宏用于擴展表達式使其與下一個被傳遞參數具有相同的類型和值。
// 對于缺省值,va_arg 可以用字符、無符號字符和浮點類型。
// 在第一次使用va_arg 時,它返回表中的第一個參數,后續的每次調用都將返回表中的
// 下一個參數。這是通過先訪問AP,然后把它增加以指向下一項來實現的。
// va_arg 使用TYPE 來完成訪問和定位下一項,每調用一次va_arg,它就修改AP 以指示
// 表中的下一參數。
#define va_arg(AP, TYPE) \
(AP += __va_rounded_size (TYPE), \
*((TYPE *) (AP - __va_rounded_size (TYPE))))

#endif /* _STDARG_H */

轉載于:https://www.cnblogs.com/mywolrd/archive/2008/11/19/1930716.html

總結

以上是生活随笔為你收集整理的C++:函数参数不确定时用cstdarg(stdarg.h)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。