一、什么是可變參數
在C語言編程中有時會遇到一些參數個數可變的函數,例如printf(),scanf()函數,其函數原型為:
int printf(const char* format,…),int scanf(const char *format,…);它除了有一個參數format固定以外,后面跟着的參數的個數和類型是可變的(用三個點“…”做參數占位符),實際調用時可以有以下的形式:
printf(“%d”,i); printf(“%d,%c”,i,j);
二、C語言---簡單的可變參數例子(實現思想)
1、整型數據的輸出
#include <stdio.h> #include <stdarg.h> void ar_cnt(int cnt,...); void ar_cst(char const *s,...); int main(int argc, char* argv[]) { int in_size =_INTSIZEOF(int); printf("int_size=%d\n",in_size); ar_cnt(5,1,2,3,4); return 0; } void ar_cnt(int cnt,...) { int value1=0; int i=0; int arg_cnt = cnt; va_list arg_ptr; va_start(arg_ptr,cnt); for(i=0;i<cnt;i++) { value1=va_arg(arg_ptr,int); printf("posation %d=%d\n",value1,i+1); } va_end(arg_ptr); }
運行結果:
2、字符串的輸出
#include <stdio.h> #include <stdarg.h> void PrintLines(char *first,...) { char *str; va_list v1; str = first; va_start(v1,first); do { printf("%s\n",str); str=va_arg(v1,char*); } while (str != NULL ); va_end(v1); } int main(int argc, char* argv[]) { PrintLines("First","Second","Third","Fourth",NULL); return 0; }
運行結果:
3、找出最大數
#include <stdio.h> #include <stdarg.h> int FindMax(int amount,...) { int i,val,great; va_list v1; va_start(v1,amount); great=va_arg(v1,int); for(i=1;i<amount;i++) { val=va_arg(v1,int); great=(great>val)?great:val; } va_end(v1); return great; } int main(int argc, char* argv[]) { int max=FindMax(5,100,20,456,102,4,300); printf("The Max one is %d\n",max); return 0; }
運行結果:
三、對va_arg,va_list,va_start,va_end,_INTSIZEOF剖析
- 內存對齊 #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
具體請參考:http://blog.csdn.net/swell624/article/details/3210779 - 可變參數用到以下宏函數
<1>原型: void va_start(va_list arg_ptr,prev_param);
功能:以固定參數的地址為起點確定變參的內存起始地址,獲取第一個參數的首地址
返回值:無
<2>原型:va_list 類型的變量,va_list arg_ptr ,這個變量是指向參數地址的指針,因為得到參數的地址之后,再結合參數的類型,才能得到參數的值。
<3>原型:type va_arg(va_list arg_ptr,type);
功能:獲取下一個參數的地址
返回值:根據傳入參數類型決定返回值類型
<4>原型:void va_end(va_list arg_ptr);
功能:將arg_ptr指針置0
返回值:無
- 使用可變參數應該有以下步驟:
⑴在程序中將用到以下這些宏:
void va_start( va_list arg_ptr, prev_param );
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );
va在這里是variable-argument(可變參數)的意思.
這些宏定義在stdarg.h中,所以用到可變參數的程序應該包含這個頭文件.
⑵函數里首先定義一個va_list型的變量,這里是arg_ptr,這個變量是指向參數地址的指針.因為得到參數的地址之后,再結合參數的類型,才能得到參數的值。
⑶然后用va_start宏初始化⑵中定義的變量arg_ptr,這個宏的第二個參數是可變參數列表的前一個參數,也就是最后一個固定參數。
⑷然后依次用va_arg宏使arg_ptr返回可變參數的地址,得到這個地址之后,結合參數的類型,就可以得到參數的值。然后進行輸出。
⑸設定結束條件,這里的條件就是判斷參數值是否為-1。注意被調的函數在調用時是不知道可變參數的正確數目的,程序員必須自己在代碼中指明結束條件。至於為什么它不會知道參數的數目,讀者在看完下面這幾個宏的內部實現機制后,自然就會明白。
三、參考文獻:
http://www.chineselinuxuniversity.net/articles/26262.shtml
http://www.cnblogs.com/wangyonghui/archive/2010/07/12/1776068.html
http://www.2cto.com/kf/201204/129038.html