快捷搜索:  汽车  科技

c函数参数怎么用(可变参数列表CC)

c函数参数怎么用(可变参数列表CC)#elif defined(_M_IX86) #define _INTsizeof(n) ( (sizeof(n) sizeof(int) - 1) & ~(sizeof(int) - 1) ) #define _crt_va_start(ap v) ( ap = (va_list)_ADDRESSOF(v) _INTSIZEOF(v) ) #define _crt_va_arg(ap t) ( *(t *)((ap = _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define _crt_va_end(ap) ( ap = (va_list)0 ) #elif defined(_M_IA64)很明显va_list就是一个类型重命名;va_list实际上就是char*型,简言之va_list arg就是声明了一个字符型指针ar

可变参数列表:

在我们一般经常使用的函数中,函数列出了期望接受的参数,但函数原型只能显示固定的参数,那么,如何让一个函数在不同的时候接受不同数目的参数呢!使用可变参数列表就可实现,当一个函数事先不确定有多少个参数但是可以接受一个或多个参数,可以使得函数可以接受1个以上的任意多个参数。

可变参数列表是通过宏来实现的,这些宏定义在stdarg.h头文件中,在这个头文件中声明了 一个类型va_list和三个宏va_start、va_arg、va_end配合使用,访问参数的值。

可变参数函数的原型声明格式为:type VAFunction(type arg1 type arg2 … ); 参数可以分为两部分:个数确定的固定参数和个数可变的可选参数。函数至少需要一个固定参数,固定参数的声明和普通函数一样;可选参数由于个数不确定,声明时用"…"表示。固定参数和可选参数共同构成一个函数的参数列表。

举个例子理解:比方求指定个数的平均值

#include <stdio.h> #include <stdarg.h> int average(int n ...) //定义一个函数,实现可变参数 { va_list arg; //定义一个变量arg为va_list类型 int i = 0; int sum = 0; va_start(arg n); for(i=0; i<n; i ) //循环获取参数 { sum = va_arg(arg int); } return sum/n; va_end(arg); } int main() { int ret1 = 0; int ret2 = 0; ret1 = average(3 1 2 3); ret2 = average(4 2 3 3 5); printf("%d\n" ret1); printf("%d\n" ret2); return 0; }

程序结果

c函数参数怎么用(可变参数列表CC)(1)

在vs中我们可以转到定义处查看各个类型和宏具体是怎样实现的

1、首先va_list arg;

#elif defined(_M_IX86) #define _INTsizeof(n) ( (sizeof(n) sizeof(int) - 1) & ~(sizeof(int) - 1) ) #define _crt_va_start(ap v) ( ap = (va_list)_ADDRESSOF(v) _INTSIZEOF(v) ) #define _crt_va_arg(ap t) ( *(t *)((ap = _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define _crt_va_end(ap) ( ap = (va_list)0 ) #elif defined(_M_IA64)

很明显va_list就是一个类型重命名;va_list实际上就是char*型,简言之va_list arg就是声明了一个字符型指针arg。

2、va_start(arg n);

#elif defined(_M_IX86) #define _INTSIZEOF(n) ( (sizeof(n) sizeof(int) - 1) & ~(sizeof(int) - 1) ) #define _crt_va_start(ap v) ( ap = (va_list)_ADDRESSOF(v) _INTSIZEOF(v) ) #define _crt_va_arg(ap t) ( *(t *)((ap = _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define _crt_va_end(ap) ( ap = (va_list)0 ) #elif defined(_M_IA64)

_INTSIZEOF(n)整个做的事情就是将n的长度化为int长度的整数倍
va_srart(ap v)就是把上面的字符指针向后移动,跳过第一个参数n的地址。

3、va_arg(args int)

#define _crt_va_end(ap) ( ap = (va_list)0 )

va_arg(args int) 就是循环获取到可变参数列表中的参数,args指向下一个参数地址,返回的则是当前参数地址。
4、va_end(arg);

#define _crt_va_end(ap) ( ap = (va_list)0 )

当访问完毕最后一个参数时,用VA_END宏结束可变参数的获取。

可变参数列表的缺陷:

1、可变参数必须从头到尾逐个访问。如果你在访问了几个可变参数之后想半途
终止,这是可以的,但是,如果你想一开始就访问参数列表中间的参数,那
是不行的

2、参数列表中至少有一个命名参数。如果连一个命名参数都没有,就无法使用
va_start。

3、如果在va_arg中指定了错误的类型,结果无法预测,因为在使用时,char、short、float类型的值实际上都作为int或double类型的值传递给函数。

猜您喜欢: