int printf(const char *format, ...);
透過 ... 表示參數個數可變,配合 format 字串解析實際引數。
核心包含一個資料結構與三個巨集:
va_list:引數列表指標va_start(ap, last_fixed):初始化 ap 指向第一個可變參數va_arg(ap, type):取得目前參數並推進 apva_end(ap):清理(通常為空操作)#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
void myprintf(char *format, ...) {
va_list ap;
va_start(ap, format);
char buf[64];
int pos = 0;
while (format[pos]) {
if (format[pos] == '%') {
pos++;
switch (format[pos]) {
case 'd': case 'u': {
int val = va_arg(ap, int);
sprintf(buf, "%d", val);
write(STDOUT_FILENO, buf, strlen(buf));
break;
}
case 'f': {
double val = va_arg(ap, double);
sprintf(buf, "%f", val);
write(STDOUT_FILENO, buf, strlen(buf));
break;
}
}
pos++;
} else {
write(STDOUT_FILENO, &format[pos], 1);
pos++;
}
}
va_end(ap);
}
int main() {
myprintf("i = %d, u = %u, f = %f\n", -1, 5, 0.2);
return 0;
}
輸出:i = -1, u = 5, f = 0.200000
typedef char *va_list; #define _AUPBND (sizeof(acpi_native_int) - 1) // 對齊邊界 #define _ADNBND (sizeof(acpi_native_int) - 1) #define _bnd(X, bnd) (((sizeof(X)) + (bnd)) & (~(bnd))) #define va_start(ap, A) (void)((ap) = (((char *)&(A)) + _bnd(A, _AUPBND))) #define va_arg(ap, T) (*(T *)(((ap) += _bnd(T, _AUPBND)) - _bnd(T, _ADNBND))) #define va_end(ap) (void)0
char*,指向堆疊上參數區域_bnd 確保參數按機器字長對齊存取C 函數呼叫慣例(如 __cdecl)將參數由右向左壓入堆疊,參數在記憶體中連續分佈。固定參數位置已知,可透過指標運算遍歷後續可變參數。
float 傳遞時會提升為 double,va_arg 需用 doubleprintf 的格式字串)