头文件stdarg.h
想要在C语言中写变参函数,首先要知道va_list,va_start,va_arg,va_end,它们都包含在头文件stdarg.h中。
- va_list 为数据类型,用于定义储存参数列表的地址的指针变量。
- va_start为宏定义,作用是将第一个参数后的地址赋给va_list类型定义的指针变量。
- va_arg 为宏定义,作用是取出参数列表的参数值。
- va_end为宏定义,作用是将va_list类型定义的指针变量指向空地址。
- 在stdarg.h头文件中,它们是被这样定义的:
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
typedef void *va_list
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
目前我没有办法理解_INTSIZEOF(n)是做什么的,在本篇博客中只讲讲如何定义一个变参函数。
定义一个变参的加法函数
#include <stdio.h>
#include <stdarg.h>
int easy_sum(int numbers,...) {
int result = 0;
va_list argumen;//定义参数列表的指针变量
va_start(argumen, numbers);//将第一个可选参数地址赋给参数列表的指针变量
while(numbers--) {
result += va_arg(argumen,int); //取出当前指针变量所指内存空间的参数值,然后将下一个参数的地址赋给指针变量。
}
va_end(argumen);
return result;
}
int main() {
int n = 4;
printf("%d\n", easy_sum(n,3,5,7,9));
return 0;
}
C语言定义变参函数的缺点
- 想要所有入参都是有意义的,即在函数中用到所有入参,则变参函数的第一个参数必须能够用于在函数体中得出一共有多少个入参。比如我上面所写的加法函数,第一个入参n就是多少个数值相加;还有系统的printf函数,它的第一个入参是字符串,字符串中的占位符就能够指出有多少个其他入参。
- va_arg想要使用获得参数的数值,是需要提前知道当前参数的数据类型才行。