一、可变参数
有时,您可能会碰到这样的情况,您希望函数带有可变数量的参数,而不是预定义数量的参数。C 语言为这种情况提供了一个解决方案,它允许您定义一个函数,能根据具体的需求接受可变数量的参数。下面的实例演示了这种函数的定义。
int func(int, ... ) {
.
.
.
}
int main(){
func(2, 2, 3);
func(3, 2, 3, 4);
}
二、函数参数的传递原理
函数参数是以数据结构:栈的形式存取,从右至左入栈。
首先是参数的内存存放格式:参数存放在内存的堆栈段中,在执行函数的时候,从最后一个开始入栈。因此栈底高地址,栈顶低地址,举个例子如下:
void func(int x, float y, char z);
那么,调用函数的时候,实参 char z 先进栈,然后是 float y,最后是 int x
,因此在内存中变量的存放次序是x->y->z
,因此,从理论上说,我们只要探测到任意一个变量的地址,并且知道其他变量的类型,通过指针移位运算,则总可以顺藤摸瓜找到其他的输入变量。
三、可变参数相关函数
函数\宏 | 描述 |
---|---|
typedef char* va_list; | 这是一个适用于 va_start()、va_arg() 和 va_end() 这三个宏存储信息的类型。 |
void va_start(va_list ap, last_arg) ; | 初始化 ap 变量。 这个宏必须在使用 va_arg 和 va_end 之前被调用。 参数: ap 这是一个 va_list 类型的对象,它用来存储通过 va_arg 获取额外参数时所必需的信息。last_arg 是最后一个传递给函数的已知的固定参数,即省略号之前的参数。 |
type va_arg ( va_list ap, type ); | 返回函数参数列表中类型为 type 的下一个参数。 参数: ap 这是一个 va_list 类型的对象,存储了有关额外参数和检索状态的信息。type 这是一个类型名称。该类型名称是作为扩展自该宏的表达式的类型来使用的。 |
void va_end ( va_list ap ); | 允许使用了 va_start 宏的带有可变参数的函数返回。如果在从函数返回之前没有调用 va_end,则结果为未定义。 |
int vsprintf(char *str, const char *format, va_list arg) | 使用参数列表发送格式化输出到字符串。 参数: str 这是指向一个字符数组的指针,该数组存储了 C 字符串。format 是字符串,包含了要被写入到字符串 str 的文本格式。arg 一个表示可变参数列表的对象。 |
四、示列
1.1 示列一
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
void tLog(char *sInfo, ...);
int main(int argc, char *argv[]) {
char str[4+1] = {0};
strcpy(str,"INFO");
tLog(str,argv[1],argv[2],argv[3]);
return 0;
}
void tLog(char *sInfo, ...) {
char *str = NULL;
char *str1 = NULL;
char *str2 = NULL;
va_list sArgv; // 申请参数列表变量
va_start(sArgv, sInfo); // 申明最后一个传递给函数的已知的固定参数
/* 依次读取固定参数 sInfo 后的 参数 */
str = va_arg(sArgv, char*);
str1 = va_arg(sArgv, char*);
str2 = va_arg(sArgv, char*);
va_end(sArgv);
printf("运行输出:[%s,%s%s%s]\n",sInfo,str,str1,str2);
}
1.2 vsprintf
#include <stdio.h>
#include <stdarg.h>
char buffer[80];
int vspfunc(char *format, ...)
{
va_list aptr;
int ret;
va_start(aptr, format);
ret = vsprintf(buffer, format, aptr);
va_end(aptr);
return(ret);
}
int main()
{
int i = 5;
float f = 27.0;
char str[50] = "mp.csdn.net";
vspfunc("%d %f %s", i, f, str);
printf("%s\n", buffer);
return(0);
}