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

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

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

2020-02-24 14:29:44
字體:
來源:轉載
供稿:網友

當我們編寫一個變量函數的時候,可能會遇到很多問題,因此在不必要的情況下不需要使用變量參數。如果在C++中,我們應該使用C++的多態性來實現可變參數的功能,今天武林技術頻道小編將著重講解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
日韩欧美成人精品| 国产小视频91| 国产免费成人av| 91热福利电影| 国产精品一区二区女厕厕| 精品成人在线视频| 538国产精品一区二区免费视频| 色一情一乱一区二区| 日韩在线视频二区| 日韩美女视频中文字幕| 久久久国产精彩视频美女艺术照福利| 国产美女91呻吟求| 欧美亚洲另类视频| 亚洲自拍偷拍第一页| 国产精品中文在线| 国产精品96久久久久久又黄又硬| 久久久免费av| 亚洲欧洲国产一区| y97精品国产97久久久久久| 亚洲精品免费在线视频| 亚洲国产精品久久久久秋霞蜜臀| 国产精品视频公开费视频| 91禁外国网站| 日韩美女在线观看一区| 日韩精品视频在线| 日韩高清中文字幕| 亚洲精品美女在线观看播放| 国产精品pans私拍| 成人免费淫片视频软件| 午夜精品久久久久久久99热| 亚洲欧美激情一区| 国产亚洲福利一区| 亚洲第一精品电影| 日韩男女性生活视频| 久久国产精品99国产精| 欧美日本亚洲视频| 国产91精品网站| 国产精品久久久久久影视| 日韩在线一区二区三区免费视频| 亚洲永久免费观看| 日韩精品极品视频| 日韩欧美a级成人黄色| 日韩一区二区欧美| 欧美日韩亚洲成人| 亚洲欧美成人在线| 亚洲欧洲日本专区| 日韩成人av在线播放| 国产欧美日韩精品专区| 国产精品国产三级国产aⅴ浪潮| 亚洲欧洲美洲在线综合| 成人免费视频在线观看超级碰| 青草青草久热精品视频在线网站| 亚洲一区二区久久久久久久| 1769国内精品视频在线播放| 色系列之999| 久久久极品av| 亚洲天堂av综合网| 97高清免费视频| 成人综合网网址| 日本亚洲欧美成人| 日韩美女av在线免费观看| 亚洲第一精品久久忘忧草社区| 久久噜噜噜精品国产亚洲综合| 免费99精品国产自在在线| 色99之美女主播在线视频| 久久精品一区中文字幕| 日韩高清av在线| 伊是香蕉大人久久| 插插插亚洲综合网| 欧美日韩亚洲天堂| 日韩动漫免费观看电视剧高清| 国产97免费视| 亚洲一区美女视频在线观看免费| 国产精品自产拍高潮在线观看| 永久免费精品影视网站| 国产精自产拍久久久久久| 性欧美办公室18xxxxhd| 欧美日韩国产影院| 国产精品国产福利国产秒拍| 国产ts一区二区| 日韩理论片久久| 亚洲女人天堂av| 在线播放精品一区二区三区| 欧美日韩国产影院| 欧美电影在线观看网站| 欧美极品少妇xxxxⅹ裸体艺术| 日韩在线观看网站| 永久555www成人免费| 日韩在线观看免费高清完整版| 亚洲影院污污.| 亚洲春色另类小说| 97精品国产91久久久久久| 成人中文字幕+乱码+中文字幕| 久久国产视频网站| 国产成人亚洲综合青青| 欧美成人国产va精品日本一级| 亚洲va欧美va国产综合久久| 黄色成人av在线| 97成人超碰免| 色综合久久88色综合天天看泰| 高清亚洲成在人网站天堂| 性色av一区二区三区在线观看| 亚洲性xxxx| 国产精品xxxxx| 国产丝袜视频一区| 中文字幕精品久久久久| 亚洲乱码国产乱码精品精天堂| 欧美一区第一页| 久久的精品视频| 日韩中文字幕免费视频| 欧美超级乱淫片喷水| 久久久久免费精品国产| 国产精品久久久久国产a级| 九九热精品视频在线播放| 国产精品ⅴa在线观看h| 91精品久久久久久久久久久久久| 欧美精品生活片| 久久久国产影院| 日韩欧美一区视频| 中文字幕久精品免费视频| 亚洲国产精品嫩草影院久久| 亚洲欧美日韩精品| 97精品国产97久久久久久免费| 亚洲美女在线观看| 亚洲999一在线观看www| 日韩av在线精品| 98精品国产自产在线观看| 深夜福利日韩在线看| 欧美专区在线视频| 精品国产欧美一区二区三区成人| 97视频在线观看免费高清完整版在线观看| 91久久国产精品| 国模精品视频一区二区| 中文字幕免费精品一区高清| 欧美高清在线视频观看不卡| 久久久久久亚洲| 亚洲天堂免费视频| 91精品免费视频| 亚洲精品一区二区三区婷婷月| 国产精品视频专区| 狠狠色狠狠色综合日日五| 国产精品福利在线| 青青草成人在线| 在线看片第一页欧美| 91精品国产免费久久久久久| 好吊成人免视频| 久久免费观看视频| 中文字幕精品国产| 亚洲第一区第二区| 亚洲视频自拍偷拍| 亚洲色图欧美制服丝袜另类第一页| 久久6免费高清热精品| 91av中文字幕| 国产在线观看91精品一区| 亚洲日韩中文字幕| 国产精品jvid在线观看蜜臀| 欧美乱妇40p| 国产成人在线一区二区| 精品高清一区二区三区| 中文字幕亚洲综合久久| 国产精品第三页| 久久久久一本一区二区青青蜜月| 欧美大片在线影院| 亚洲欧美另类在线观看|