亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C/C++可變參數的使用

2020-01-26 15:52:39
字體:
來源:轉載
供稿:網友

可變參數即表示參數個數可以變化,可多可少,也表示參數的類型也可以變化,可以是int,double還可以是char*,類,結構體等等??勺儏凳菍崿Fprintf(),sprintf()等函數的關鍵之處,也可以用可變參數來對任意數量的數據進行求和,求平均值帶來方便(不然就用數組或每種寫個重載)。在C#中有專門的關鍵字parame,但在C,C++并沒有類似的語法,不過幸好提供這方面的處理函數,本文將重點介紹如何使用這些函數。

第一步 可變參數表示
用三個點…來表示,查看printf()函數和scanf()函數的聲明:
int printf(const char *, ...);
int scanf(const char *, ...);
這三個點用在宏中就是變參宏(Variadic Macros),默認名稱為__VA_ARGS__。如:
#define WriteLine(...) { printf(__VA_ARGS__); putchar('/n');}
再WriteLine("MoreWindows");
考慮下printf()的返回值是表示輸出的字節數。將上面宏改成:
#define WriteLine (...) printf(__VA_ARGS__) + (putchar('/n') != EOF ? 1: 0);
這樣就可以得到WriteLine宏的返回值了,它將返回輸出的字節數,包括最后的'/n'。如下例所示i和j都將輸出12。

復制代碼 代碼如下:

       int i = WriteLine("MoreWindows");
       WriteLine("%d", i);
       int j = printf("%s/n", "MoreWindows");
       WriteLine("%d", j);

第二步 如何處理va_list類型
函數內部對可變參數都用va_list及與它相關的三個宏來處理,這是實現變參參數的關鍵之處。

在<stdarg.h>中可以找到va_list的定義:
typedef char *  va_list;
再介紹與它關系密切的三個宏要介紹下:va_start(),va_end()和va_arg()。

同樣在<stdarg.h>中可以找到這三個宏的定義:
#define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_end(ap)      ( ap = (va_list)0 )
#define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

其中用到的_INTSIZEOF宏定義如下:
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

來分析這四個宏:
va_end(ap)這個最簡單,就是將指針置成NULL。
va_start(ap,v)中ap = (va_list)&v + _INTSIZEOF(v)先是取v的地址,再加上_INTSIZEOF(v)。_INTSIZEOF(v)就有點小復雜了。( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )全是位操作,看起來有點麻煩,其實不然,非常簡單的,就是取整到sizeof(int)。比如sizeof(int)為4,1,2,3,4就取4,5,6,7,8就取8。對x向n取整用C語言的算術表達就是((x+n-1)/n)*n,當n為2的冪時可以將最后二步運算換成位操作――將最低 n - 1個二進制位清 0就可以了。
va_arg(ap,t)就是從ap中取出類型為t的數據,并將指針相應后移。如va_arg(ap, int)就表示取出一個int數據并將指針向移四個字節。

因此在函數中先用va_start()得到變參的起始地址,再用va_arg()一個一個取值,最后再用va_end()收尾就可以解析可變參數了。

第三步 vfprintf()函數和vsprintf()函數
vfprintf()這個函數很重要,光從名字上看就知道它與經常使用的printf()函數有很大的關聯。它有多個重載版本,這里講解最常用的一種:

函數原型

復制代碼 代碼如下:

int vfprintf(
   FILE *stream,
   const char *format,
   va_list argptr
);

第一個 參數為一個FILE指針。FILE結構在C語言的讀寫文件必不可少。要對屏幕輸出傳入stdout。
第二個 參數指定輸出的格式。
第三個 參數是va_list類型,這個少見,但其實就是一個char*表示可變參參數的起始地址。
返回值:成功返回輸出的字節數(不包括最后的'/0'),失敗返回-1。

vsprintf()與上面函數類似,就只列出函數原型了:
復制代碼 代碼如下:

int vsprintf(
   char *buffer,
   const char *format,
   va_list argptr
);

還有一個int _vscprintf(const char *format, va_list argptr );可以用來計算vsprintf()函數中的buffer字符串要多少字節的空間。

代碼范例
下面就給出了自己實現的printf()函數(注1)與WriteLine()函數
復制代碼 代碼如下:

int Printf(char *pszFormat, ...)
{
       va_list   pArgList;

       va_start(pArgList, pszFormat);
       int nByteWrite = vfprintf(stdout, pszFormat, pArgList);
       va_end(pArgList);

       return nByteWrite;
}

int WriteLine(char *pszFormat, ...)
{
       va_list   pArgList;

       va_start(pArgList, pszFormat);
       int nByteWrite = vfprintf(stdout, pszFormat, pArgList);
       if (nByteWrite != -1)
              putchar('/n'); //注2
       va_end(pArgList);

       return (nByteWrite == -1 ? -1 : nByteWrite + 1);
}

調用與printf()函數相同。
再給出一個用可變參數來求和,遺憾的在C,C++中無法確定傳入的可變參數的個數(printf()中是通過掃描'%'個數來確實參數的個數的),因此要么就要指定個數,要么在參數的最后要設置哨兵數值:
設置哨兵數值:
復制代碼 代碼如下:

const int GUARDNUMBER = 0; //哨兵標識
//變參參數的個數無法確定,在printf()中是通過掃描'%'個數,在這通過設置哨兵標識來確定變參參數的終止
int MySum(int i, ...)
{
       int sum = i;
       va_list argptr;

       va_start(argptr, i);
       while ((i = va_arg(argptr, int)) != GUARDNUMBER)
              sum += i;
       va_end(argptr);

       return sum;
}

可以這樣的調用:   printf("%d/n", MySum(1, 3, 5, 7, 9, 0));
但不可以直接傳入一個0:   printf("%d/n", MySum(0)); //error
指定個數:
復制代碼 代碼如下:

int MySum(int nCount, ...)
{
       if (nCount <= 0)
              return 0;

       int sum = 0;
       va_list argptr;

       va_start(argptr, nCount);
       for (int i = 0; i < nCount; i++)
              sum += va_arg(argptr, int);
       va_end(argptr);

       return sum;
}

調用時第一個參數表示后面參數的個數如:
復制代碼 代碼如下:

       printf("%d/n", MySum(5, 1, 3, 5, 7, 9));
       printf("%d/n", MySum(0));

代碼所用的頭文件:
#include <stdarg.h>
#include <stdio.h>

可變參數的使用方法遠遠不止上述幾種,不過在C,C++中使用可變參數時要小心,在使用printf()等函數時傳入的參數個數一定不能比前面的格式化字符串中的'%'符號個數少,否則會產生訪問越界,運氣不好的話還會導致程序崩潰。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲第一区第一页| 亚洲综合一区二区不卡| 国产主播在线一区| 欧美国产欧美亚洲国产日韩mv天天看完整| 91精品国产综合久久香蕉最新版| 亚洲亚裔videos黑人hd| 欧美限制级电影在线观看| 91亚洲va在线va天堂va国| 亚洲福利视频免费观看| 97久久精品人人澡人人爽缅北| 91久久在线观看| 久久精品国产久精国产思思| 亚洲国模精品私拍| 欧美日本国产在线| 午夜精品三级视频福利| 日韩免费av片在线观看| 在线国产精品播放| 欧美国产日韩一区二区在线观看| 成人欧美一区二区三区黑人孕妇| 国产精品自拍偷拍视频| 色婷婷久久一区二区| 国内精品国产三级国产在线专| 久久综合久中文字幕青草| 精品国产乱码久久久久酒店| 国产丝袜一区视频在线观看| 国产99久久久欧美黑人| 国模吧一区二区| 91中文字幕在线观看| 久久久久久久亚洲精品| 92国产精品久久久久首页| 91国内免费在线视频| 亚洲欧美三级在线| 欧美疯狂性受xxxxx另类| 69av在线视频| 国产日韩一区在线| 亚洲黄色免费三级| 亚洲高清久久网| 亚洲欧洲黄色网| 日韩av有码在线| 欧美极品美女视频网站在线观看免费| 成人信息集中地欧美| 国产精品午夜视频| 亚洲欧美精品在线| 色偷偷91综合久久噜噜| 成人免费午夜电影| 成人免费高清完整版在线观看| 久久久999精品免费| 亚洲视频专区在线| 欧美在线不卡区| 国产女人精品视频| 亚洲色图综合久久| 亚洲国产精品999| 色综合久久久久久中文网| 国内精品模特av私拍在线观看| 一本色道久久综合亚洲精品小说| 美女性感视频久久久| 亚洲aa中文字幕| 久久久久久久一区二区| 国产欧美中文字幕| 91po在线观看91精品国产性色| 亚洲va久久久噜噜噜久久天堂| 亚洲精品福利在线观看| 日韩精品视频在线观看网址| 国产精品美女在线观看| 最新国产精品拍自在线播放| 日韩欧美999| 久久视频在线直播| 欧美二区乱c黑人| 一区二区三区回区在观看免费视频| 久久久久久久香蕉网| 亚洲一区二区三区久久| 黄色一区二区在线观看| 国产91精品久久久久| 色综合导航网站| 亚洲免费精彩视频| 在线视频欧美性高潮| 日韩av一区在线观看| 亚洲精品视频播放| 国产精品视频一| 91精品久久久久久久久久久久久| 亚洲一级一级97网| 亚洲综合一区二区不卡| 亚洲无av在线中文字幕| 在线观看国产成人av片| 都市激情亚洲色图| 亚洲裸体xxxx| 国产综合在线视频| 欧美日韩福利在线观看| 国产成人avxxxxx在线看| 5278欧美一区二区三区| 国产日韩欧美在线播放| 欧美激情在线播放| 亚洲成人1234| 中文字幕亚洲在线| 国产91在线高潮白浆在线观看| 成人在线视频网| 久久久久久999| 国产精品久久久久久久久影视| 色婷婷综合成人av| 日韩欧美在线视频观看| 成人在线视频福利| 在线一区二区日韩| 亚洲精品狠狠操| 亚洲国产另类 国产精品国产免费| 精品久久久国产| 欧美性猛交xxxx富婆弯腰| 欧美亚洲伦理www| 尤物九九久久国产精品的分类| 欧美www视频在线观看| 久久久精品一区二区三区| 日韩美女在线看| 97久久超碰福利国产精品…| 欧美亚洲成人xxx| 日韩精品在线视频观看| 91精品国产综合久久香蕉最新版| 精品日本高清在线播放| 国产精品毛片a∨一区二区三区|国| 欧美xxxx14xxxxx性爽| 色老头一区二区三区在线观看| 成人黄色片网站| 91a在线视频| 亚洲天堂男人天堂| 97精品欧美一区二区三区| 久久精品电影一区二区| 国产91精品网站| 亚洲电影免费观看高清完整版在线| 久久伊人精品天天| y97精品国产97久久久久久| 国产精品久久综合av爱欲tv| 亚洲第一男人天堂| 欧美激情久久久久| 欧美成人小视频| 欧美肥婆姓交大片| 欧美资源在线观看| 欧美国产乱视频| 激情av一区二区| 国产精彩精品视频| 欧亚精品在线观看| 亲爱的老师9免费观看全集电视剧| 欧美一级黑人aaaaaaa做受| 少妇精69xxtheporn| 国外成人免费在线播放| 亚洲精品av在线播放| 欧美激情在线视频二区| 色樱桃影院亚洲精品影院| 911国产网站尤物在线观看| 日韩激情在线视频| 尤物九九久久国产精品的特点| 久久精品国产免费观看| 奇米成人av国产一区二区三区| 日韩在线视频观看正片免费网站| 国产精品啪视频| 国产精品18久久久久久首页狼| 国产伊人精品在线| 亚洲精品在线视频| 欧美性猛交丰臀xxxxx网站| 成人妇女淫片aaaa视频| 欧美一级大片在线观看| 国模吧一区二区| 亚洲人成免费电影| 久久精品国产91精品亚洲| 亚洲激情国产精品| 欧美寡妇偷汉性猛交| 日本不卡免费高清视频|