Skip to content

Instantly share code, notes, and snippets.

@itczl22
Created October 30, 2016 08:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save itczl22/fc657665e7e2c622c0e94e6cabd4bbd4 to your computer and use it in GitHub Desktop.
Save itczl22/fc657665e7e2c622c0e94e6cabd4bbd4 to your computer and use it in GitHub Desktop.
c语言变长参数
/*
* 通过3个宏和一个类型实现:
* va_start va_arg va_end va_list
* 实现:
* 把参数在栈中的地址记录到va_list中, 通过一个确定参数first_num确定地址然后逐个读取值
* 通常也会在对第一个参数进行一些特殊处理以方便函数的实现
* 比如强制指定为参数个数、指定结束参数或者像printf一样使用格式占位符来
* 参数是如何获取的, 为什么要指定第一个参数:
* 函数的调用的参数会进行压栈处理, 而对参数的压栈是从右到左进行压栈
* 因此栈顶就是第一个有名参数, 而参数和参数之间存放是连续的
* 这样只要知道第一个参数的地址和类型以及其他参数的类型就可以获取各个参数的地址
*/
#include <stdio.h>
// 可变参数标准宏头文件
#include <stdarg.h>
#define END -1
// 本函数是通过指定一个值表示参数结束, 也可以把第一个参数指定为参数个数, 因实现而异
int va_sum(int first_num, ...) {
// 定义va_list数据类型变量vl, 该变量访问变长参数列表中的参数
va_list vl;
// 用第一个参数初始化参数列表, va_start根据此参数判断参数列表的起始位置
va_start(vl, first_num);
int result = first_num;
int temp = 0;
// 获取参数值, 第二个为参数值的类型,也是宏va_arg返回数值的类型。
// 宏va_arg执行完毕后自动更改对象vl, 将其指向下一个参数
while((temp = va_arg(vl, int)) != END) {
result += temp;
}
// 关闭参数列表
va_end(vl);
return result;
}
int main(void) {
int sum = va_sum(1, 2, 3, 4, 5, END);
printf("%d", sum);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment