函数的可变参数传参

函数的可变参数传参

一.前言

可变参数传参是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)
被调用函数看到的栈/寄存器里,这些值连续排布,顺序与实参顺序一致。