【C/C++开发】C语言实现函数可变参数
? ? ? ?函數(shù)原型: int printf(const char *format[,argument]...)
?????? 返 回 值: 成功則返回實(shí)際輸出的字符數(shù),失敗返回-1.
?函數(shù)說(shuō)明:
???????在printf()函數(shù)中,format后面的參數(shù)個(gè)數(shù)不確定,且類型也不確定,這些參數(shù)都存放在棧內(nèi).調(diào)用printf()函數(shù)時(shí),根據(jù)format里的格式("%d %f...")依次將棧里參數(shù)取出.而取出動(dòng)作要用到va_arg、va_end、va_start這三個(gè)宏定義,再加上va_list.
???? (1)va_list事實(shí)上是一char *類型,即:
??????????? typedef char* va_list;
???? (2)三個(gè)宏定義:
??????????? #define _INTSIZEOF(n)??? ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )?
????????????#define va_start(ap,v)???? ( ap = (va_list)&v + _INTSIZEOF(v) )?
????????????#define va_arg(ap,type)? ( *(type *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )?
????????????#define va_end(ap)????????? ( ap = (va_list)0 )?
?? 【attention】C語(yǔ)言中可變參數(shù)的原理---printf()函數(shù)?
??????????? int printf(const char* format,...);???
????? 使用過(guò)C語(yǔ)言的人所再熟悉不過(guò)的printf函數(shù)原型,它的參數(shù)中就有固定參數(shù)format和可變參數(shù)(用”…”表示).而程序員又可以用各種方式來(lái)調(diào)用printf,如:?
??????????? printf("%d ",value);???
??????????? printf("%s ",str); ??
??????????? printf("the number is %d,string is:%s ",value,str);?
?????? 可以看出,該函數(shù)的參數(shù)格式不固定,參數(shù)類型不固定.在C語(yǔ)言中使用宏來(lái)處理這些可變參數(shù).這些宏看起來(lái)很復(fù)雜,其實(shí)原理挺簡(jiǎn)單,即根據(jù)參數(shù)入棧的特點(diǎn)從最靠近第一個(gè)可變參數(shù)的固定參數(shù)開(kāi)始,依次獲取每個(gè)可變參數(shù)的地址.
?(1)宏va_start
????? 通過(guò)該宏定義可以獲取到可變參數(shù)表的首地址,并將該地址賦給指針ap.
?(2)宏va_arg
????? 通過(guò)該宏定義可以獲取當(dāng)前ap所指向的可變參數(shù),并將指針ap指向下一個(gè)可變參數(shù).注意,該宏的第二個(gè)參數(shù)為類型.
?(3)宏va_end
??????通過(guò)該宏定義可以結(jié)束可變參數(shù)的獲取.
????? 程序員通過(guò)這三個(gè)宏定義就可以實(shí)現(xiàn)對(duì)可變參數(shù)的處理.例如:
? ?#include <stdio.h> ?
??
typedef char* va_list; ??
? ?#define _INTSIZEOF(n) ? ?((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) ??
? ?#define va_start(ap,v) ? ( ap = (va_list)&v + _INTSIZEOF(v) ) ??
? ?#define va_arg(ap,type) ?( *(type *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) ??
? ?#define va_end(ap) ? ? ? ( ap = (va_list)0 ) ??
??
int cal_val(int c, ...) ??
{ ??
? ? int sum = c; ??
? ? va_list ap; ? ? ? ? ? ? ?//聲明指向char型的指針 ?
? ? va_start(ap,c); ? ? ? ? ?//獲取可變參數(shù)列表的首地址,并賦給指針ap ?
??
? ? c = va_arg(ap,int); ? ? ?//從可變參數(shù)列表中獲取到第一個(gè)參數(shù)(返回值即為參數(shù)) ?
? ? while(0 != c) ??
? ? { ??
? ? ? ? sum += c; ??
? ? ? ? c = va_arg(ap,int); ?//循環(huán)的從可變參數(shù)列表中獲取到參數(shù)(返回值即為參數(shù)) ?
? ? } ?
? ? va_end(ap); ? ? ? ? ? ? ?//結(jié)束從可變參數(shù)列表中獲取參數(shù) ?
? ? return sum; ??
} ? ?
? ?
int main(int argc, char* argv[]) ??
{ ??
? ? int value1; ?
? ? ??
? ? value1 = cal_val(1,2,3,4,5,6,7,8,9,0); ??
? ? printf("value1=%d/n",value1); ?
? ? value2 = cal_val(6,7,8,9,0); ??
? ? printf("value2=%d/n",value2); ?
? ? ??
? ? return 0; ??
} ??
轉(zhuǎn)載于:https://www.cnblogs.com/huty/p/8517288.html
總結(jié)
以上是生活随笔為你收集整理的【C/C++开发】C语言实现函数可变参数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 20162303《程序设计与数据结构》第
- 下一篇: C++中 list与vector的区别