(1)????? C語言可變參數
我們能夠從C語言的printf得出可變參數的作用。printf函數的原型例如以下:
int printf ( const char * format, ... );
通過使用可變個數參數,就是傳入的參數個數是可變的,如printf須要依據format實參傳入多個實參。
(2)????? C語言可變參數的使用
以下一個函數myprintf是自己實現的比較簡單的printf函數。不完整可是能夠說明可變參數的使用方法。
/*
* Author: guojun07
*/
#include
#include
#include
#include
void myprintf(char *format, ...) {
va_list ap;
int pos = 0;
int int_val = 0;
float f_val;
char buf[64];
memset(buf, 0, 64);
// 得到全部的參數放到下一個list中ap中
va_start(ap, format);
while (format[pos] != ' ') {
// 推斷'%'。表示要得到下一個參數
if (format[pos] == '%') {
pos ++;
switch(format[pos]) {
case 'd':
case 'u':
// 得到ap中的下一個參數
int_val = va_arg(ap, int);
sprintf(buf, "%d", int_val);
// 將數據寫到標準輸出
write(STDOUT_FILENO, buf, strlen(buf));
memset(buf, 0, 64);
pos ++;
break;
case 'f':
// 得到ap中的下一個參數
f_val = (float)va_arg(ap, double);
sprintf(buf, "%f", f_val);
// 將數據寫到標準輸出
write(STDOUT_FILENO, buf, strlen(buf));
memset(buf, 0, 64);
pos ++;
break;
default:
break;
}
} else {
write(STDOUT_FILENO, &(format[pos]), 1);
pos ++;
}
}
}
int main(void){
myprintf("this is a testing, i = %d, u = %u, f = %f
", -1, 5, 0.2);
return 0;
}
程序的數據結果例如以下:
guojun8@guojun8-desktop:~/test/valist$ ./main
this is a testing, i = -1, u = 5, f = 0.200000
(3)????? 實現
以下介紹C語言可變長度參數的實現。事實上現與一個數據結構(va_list)和三個宏(va_start, va_end, va_arg)相關,從源代碼中能夠看到這些實現以下的來自linux內核源代碼中的文件(include/acpi/platform/acenv.h)
#ifndef _VALIST
#define _VALIST
typedef char *va_list;
#endif??????? /* _VALIST */
/*
* Storage alignment properties
*/
#define? _AUPBND??????????????? (sizeof (acpi_native_int) - 1)
#define? _ADNBND??????????????? (sizeof (acpi_native_int) - 1)
/*
* Variable argument list macro definitions
*/
#define _bnd(X, bnd)??????????? (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T)?????????? (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap)????????????? (void) 0
#define va_start(ap, A)???????? (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
a)???????? va_list
從實現中能夠看出va_list類型實際上就是一個指針。
b)??????? va_start
這個宏的作用是將T所指向的參數后面的內容放到ap中。當中_bnd (A,_AUPBND)是返回A的size并與系統的機器位數對齊。由于參數在棧中的地址一定是與系統的字長對齊的,當中acpi_native_int就表示機器字長。
c)???????? va_end
這個宏的作用就是返回0。
d)??????? va_arg
這個宏的作用是取得ap指向的當前的參數,并將ap指向參數列表中的下一個參數。