C語言可變引數簡析
今天在看程式碼的時候,看到了這樣一段除錯的程式碼,搞不清楚(...)這個是什麼意思,看了下相關資料,簡單記錄下。
#ifdef DEBUG
#define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)
#else
#define DBG(...)
#endif
1、printf程式碼
1 2 |
(“a=%d,b=%s,c=%c”,a,b,c);其引數個數為4個。 |
如何編寫可變引數函式呢?我們首先來看看printf函式原型是如何定義的。
在linux下,輸入man 3 printf,可以看到prinf函式原型如下:
1 2 3 |
|
後面的三個點...表示printf引數個數是不定的.
如何實現可變引數函式?
2. 編寫可變函式準備
為了編寫可變引數函式,我們通常需要用到<stdarg.h>標頭檔案下定義的以下函式:
1 2 3 4 |
|
其中:
va_list是用於存放參數列表的資料結構。
va_start函式根據初始化last來初始化引數列表。
va_arg函式用於從引數列表中取出一個引數,引數型別由type指定。
va_copy函式用於複製引數列表。
va_end函式執行清理引數列表的工作。
上述函式通常用巨集來實現,例如標準ANSI形式下,這些巨集的定義是:
1 2 3 4 5 |
|
使用巨集_INTSIZEOF是為了按照整數字節對齊指標,因為c呼叫協議下面,引數入棧都是整數字節(指標或者值)。
4、用va_list實現vprintf()示例
#include <stdio.h>
#include <stdarg.h>
void my_printf(const char *format, ...)
{
int n;
va_list arg_list;
va_start(arg_list, arg_list);
n = vprintf(format, arg_list);
va_end(arg_list);
}
int main(int argc, char *argv[])
{
int ai = 0;
my_printf("%d\n", ai);
return 0;
}
5、C語言可變引數函式簡單例項
引數列表的格式是強制性引數在前,後面跟著一個逗號和省略號(...),這個省略號代表可選引數。
可變引數函式要獲取可選引數時,必須通過一個型別為 va_list 的物件,它包含了引數資訊。這種型別的物件也稱為引數指標(argument pointer),它包含了棧中至少一個引數的位置。可以使用這個引數指標從一個可選引數移動到下一個可選引數,由此,函式就可以獲取所有的可選引數。va_list 型別被定義在標頭檔案 stdarg.h 中。
一個簡單的例子,說明可變引數的用法
#include <stdio.h>
#include <stdarg.h>
int simple(int num,...) //num代表了要傳遞的可變引數的總數
{
int i, result=0;
va_list vl; //va_list指標,用於va_start取可變引數,為char*
va_start(vl,num); //取得可變引數列表中的第一個值
printf("num:%d, vl:%d\n",num,*vl);
//訪問所有賦給valist的值
for (i = 0; i < (num-1); i++)//這裡num表示可變引數列表中有多少個引數
{
//這裡把vl往後跳過4個位元組(sizeof(int)大小)指向下一個引數,返回的是當前引數(而非下一個引數)
result = va_arg(vl, int);
//這裡列印下,可以看出,vl總是指向result後面的那個引數
printf("in for result:%d, *vl:%d\n", result, *vl);
}
va_end(vl);//結束標誌
return result;
}
int main(int argc, char **argv)
{
simple(5,1,2,3,4,5);
return 0;
}
執行結果如下:
原文地址:http://www.runoob.com/cprogramming/c-variable-arguments.html