举例分析可变参数函数实现的过程
2018-03-12 21:54
309 查看
求总和函数(可变参数形式)
函数栈调用
对于C语言,其调用遵循_cdecl规则:
1.所有参数从右到左依次入栈。
2.这些参数由调用者清除,称为手动清除。
3.被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。(简化的将就是调用参数的类型和数量不会产生编译阶段的错误)
以求和函数举例
![](https://img-blog.csdn.net/20180312214534833?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQVNKQkZKU0I=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
三个宏宏定义
(1)va_start
va_start宏的作用:
参数类型: ap为va_list类型指针,即为char *,v是最后一个确定的参数。其含义是它之后的参数均为可变参数。
功能:获取可变参数中的第一个参数,并将其地址保存在ap中。
_INTSIZEOF(v)宏函数是为了对齐内存。
(2)va_arg
va_arg宏的作用:
参数类型: ap为va_list类型的指针,即char,它指向当前需要获取的参数。t为当前参数的类型。
功能: 获取ap当前所指向参数的指针,并将其强制转化为 *t,并进行解引用 ,然后将ap指向可变参数表的下一个参数。
(3)va_end
va_end宏的作用:
参数类型: ap为va_list类型的指针 。
功能: 使指针指向空,不在使用该指针。防止ap成为野指针,进行错误引用。实际上通常va_start与va_end是配对使用。
了解并掌握以上三个宏的使用方法以及函数栈调用的规则后。
下面开始分析求和可变参数函数的实现过程:
int average(int n,...) { int sum; va_list args; va_start(args,n); for(int i = 0;i<n;++i) { sum += va_arg(args,int); } va_end(args); return sum; }
typedef char * va_list //为char* 别名为va_list
函数栈调用
对于C语言,其调用遵循_cdecl规则:
1.所有参数从右到左依次入栈。
2.这些参数由调用者清除,称为手动清除。
3.被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。(简化的将就是调用参数的类型和数量不会产生编译阶段的错误)
以求和函数举例
int sum = sum(3,4,5,6);
三个宏宏定义
(1)va_start
#define va_start _crt_va_start #define _crt_va_start va_start(ap,v) #define va_start(ap,v) (ap = (va_list)&v + _INTSIZEOF(v)) #define _INTSIZEOF(v) ((sizeof(v) + sizeof(int) - 1) & ~(sizeof(int)-1))
va_start宏的作用:
#define va_start(ap,v) (ap = (va_list)&v + _INTSIZEOF(v)) ap = (char*)&v + (sizeof(v) + sizeof(int) - 1) & ~(sizeof(int)-1);
参数类型: ap为va_list类型指针,即为char *,v是最后一个确定的参数。其含义是它之后的参数均为可变参数。
功能:获取可变参数中的第一个参数,并将其地址保存在ap中。
#define _INTSIZEOF(v) ((sizeof(v) + sizeof(int) - 1) & ~(sizeof(int)-1))
_INTSIZEOF(v)宏函数是为了对齐内存。
(2)va_arg
#define va_arg(ap,t) (*(t*))(ap += _INTSIZEOF(t) - _INTSIZEOF(t))
va_arg宏的作用:
参数类型: ap为va_list类型的指针,即char,它指向当前需要获取的参数。t为当前参数的类型。
功能: 获取ap当前所指向参数的指针,并将其强制转化为 *t,并进行解引用 ,然后将ap指向可变参数表的下一个参数。
(3)va_end
#define va_end(ap) (ap = (va_list)0) ap = (char*)0 = NULL;
va_end宏的作用:
参数类型: ap为va_list类型的指针 。
功能: 使指针指向空,不在使用该指针。防止ap成为野指针,进行错误引用。实际上通常va_start与va_end是配对使用。
了解并掌握以上三个宏的使用方法以及函数栈调用的规则后。
下面开始分析求和可变参数函数的实现过程:
int average(int n,...) //...表示参数的类型和数量不确定 n表示传入参数的个数 { int sum; va_list args; //相当于定义 char *p; va_start(args,n); //获取可变参数列表中的第一个参数的地址并保存在p内 va_start(p,n) for(int i = 0;i<n;++i) { sum += va_arg(args,int); } va_end(args); // 等价于*p = NULL; return sum; }
相关文章推荐
- 可变参数列表实现机制与printf()函数源码分析
- 对C的printf函数的可变长参数实现的分析
- C语言可变参数函数分析与实现
- 对C的printf函数的可变长参数实现的分析
- 05 printf函数可变参数的实现原理之汇编分析
- 【转】[转]C语言可变参数函数分析与实现
- va_start,va_arg,va_end,va_list应用举例--实现可变参数的函数
- 用C语言实现参数个数可变的函数
- 如何实现VBA中函数的可变参数传递
- 可变参数函数的实现
- 可变参数函数,原理,实现,UART寄存器操作
- C语言中实现参数个数可变的函数
- 可变参数函数的实现
- Matlab中使用varargin来实现参数可变的函数
- 从printf谈可变参数函数的实现
- C语言可变参数函数的实现
- javascript用arguments数组对象实现参数变量可变的函数
- 用库函数stdarg.h实现函数参数的可变
- 使用未公开关键字在 C# 中导入外部 printf 等参数数量可变函数 [2] C# 实现
- C中可变参数函数实现