一.前言
可变参数传参是C语言的一种高级用法。
二. 用法示例
求任意个 int 类型数据的平均值。
点击查看代码
double avg_int(int count, ...)
{va_list ap; /* 2. 声明参数列表变量 */int sum = 0;va_start(ap, count); /* 3. 用最后一个固定参数初始化 */for (int i = 0; i < count; ++i)sum += va_arg(ap, int); /* 4. 逐个取 int 数据累加 */va_end(ap); /* 5. 清理 */return count ? (double)sum / count : 0.0;
}
三.参数布局
若调用函数avg_int(3, 10, 20, 30),在x86-64 System V ABI(Linux/macOS 64 位)典型布局(简化):
高地址
+-----------+
| 30 | <-- 第四个实参
+-----------+
| 20 | <-- 第三个实参
+-----------+
| 10 | <-- 第二个实参
+-----------+
| 3 | <-- 第一个实参(count)
+-----------+
| ret addr |
低地址
三个宏的真身(简化版,glibc 实现)
点击查看代码
typedef char *va_list; /* 只是字节指针 */#define va_start(ap, last) \((ap) = (char *)&(last) + sizeof(last))#define va_arg(ap, type) \(*(type *)((ap) += sizeof(type), (ap) - sizeof(type)))#define va_end(ap) \((ap) = (char *)0)