參數由右向左壓棧,呼叫者清理堆疊。記憶體連續分佈:
高位址 +----------------+ | 參數 3 (最右) | ← 最高位址 | 參數 2 | | 參數 1 | | 參數 0 (最左) | ← 最低位址(固定參數) +----------------+ 低位址
void fixed(int a, int b, int c, int d) {
// &a < &b < &c < &d(位址遞增)
// d = *(&a + 3) // 以 a 為基準推導
}
至少一個固定參數作為「錨點」,透過指標運算遍歷後續參數。
// 簡化版(假設 32 位、4 位元組對齊)
#define va_list char*
#define va_start(ap, last) \
(ap = (char*)&last + sizeof(last))
#define va_arg(ap, type) \
(*(type*)((ap += sizeof(type)) - sizeof(type)))
#define va_end(ap) ((void)0)
// 使用範例
void var_func(int fixed, ...) {
va_list ap;
va_start(ap, fixed);
int p1 = va_arg(ap, int);
double p2 = va_arg(ap, double);
char *p3 = va_arg(ap, char*);
va_end(ap);
}
// 考慮型別對齊需求
#define _ALIGN_SIZE(type) (((sizeof(type) + 3) / 4) * 4) // 4 位元組對齊
#define va_arg(ap, type) \
(*(type*)((ap += _ALIGN_SIZE(type)) - _ALIGN_SIZE(type)))
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
va_list = char* 指向參數區va_start:固定參數位址 + 對齊位移 → 首個可變參數va_arg:先推進指標(含對齊),再回溯取值_AUPBND/_ADNBND 依機器字長而定| 慣例 | 參數壓棧序 | 清理者 | 可變參數支援 |
|---|---|---|---|
__cdecl | 右→左 | 呼叫者 | 支援 |
__stdcall | 右→左 | 被呼叫者 | 不支援(參數數量固定) |
__fastcall | 前兩參數用暫存器 | 被呼叫者 | 部分支援 |