C/C++ 可变参数列表
原创
©著作权归作者所有:来自51CTO博客作者贝勒里恩的原创作品,请联系作者获取转载授权,否则将追究法律责任
C++原型与ANSI C原型的区别
ANSI C借鉴了C++中的原型,但这两种语言还有有区别的。其中最重要的区别是,为与基本C兼容,ANSI C中的原型是可选的,但在C++中,原型是必不可少的。例如,请看下面的函数声明:
void say_hi();
在C++中,括号为空与在括号中使用关键字void是等效的–意味着函数没有参数。在ANSI C中,括号为空意味着不指定参数–这意味着在后面定义参数列表。在C++中,不指定参数列表时应使用省略号:
void say_hi(...);
通常,仅当与接受可变参数的C函数(如printf())交互时才需要这样做。
以下讲解以下C/C++的可变参数列表的实际使用
我们非常熟悉的printf
函数就是一种变长参数,简化版本的函数原型即为:int printf(const char * _Format,...);
,其中,第一个参数即为必须制定的格式字符串,后面的省略号表示数量不定的参数列表。
使用上面提到的三个点表示的省略号即可达到定义一个变长参数的函数的目的,但是函数中如果获取这里面的所有参数呢?
这是要使用C语言中解决变长参数问题的若干宏定义va_start
、va_arg
、va_end
,它们均定义在stdarg.h
头文件中,以va开头(表示variable-argument可变参数),可根据预先定义的系统平台自动获取相应平台上各个数据类型的偏移量。它们的使用方法为:
va_list ap; //定义一个可变参数列表ap
va_start(ap,arg); //初始化ap指向参数arg的下一个参数
va_arg(ap,type); //获取当前参数内容并将ap指向下一个参数
va_end(ap); //释放ap
首先定义一个va_list
类型的变量ap
,然后使用va_start
初始化这个变量。初始化之后,ap即指向了参数arg后面的第一个参数,即不确定参数中的第一个。然后使用va_arg
可以取出当前ap指向的这个参数的数值,并把ap指向了下一个参数,不断的进行这个操作可以取出变长参数中的所有参数。最后使用va_end
清空这个变长参数列表。
实例如下:
下面通过一个简单的例子说明变长参数函数的具体使用方法。该函数返回输入参数指定的数据之和,其中参数的第一个变量表示这组数一共有多少个,然后紧接着对应数量的数值。
#include <iostream>
#include <cstdio>
#include <cstdarg>
int find_sum(int num,...);
int main()
{
using namespace std;
int t1 = find_sum(1, 1);
int t2 = find_sum(2, 1, 2);
int t3 = find_sum(3, 1, 2, 3);
int t4 = find_sum(4, 1, 2, 3, 4);
int t10 = find_sum(10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
cout << t1<<endl<<t2<<endl<<t3<<endl<<t4<<endl<<t10<<endl;
}
int find_sum(int num, ...)
{
va_list ap;
va_start(ap, num);
int sum = 0;
for (int i = 0; i < num; i++)
sum += va_arg(ap, int);
va_end(ap);
return sum;
}
运行结果如下:
int MainWindow::find_min(int num,...)
{
int min = 9999;
va_list p_arg;
va_start(p_arg,num);
for (int i=0; i < num; ++i)
{
int tmp = va_arg(p_arg, int);
if(tmp<min){
min = tmp;
}
}
va_end(p_arg);
return min;
}
int MainWindow::find_max(int num,...)
{
int max = -9999;
va_list p_arg;
va_start(p_arg,num);
for (int i=0; i < num; ++i)
{
int tmp = va_arg(p_arg, int);
if(tmp>max){
max = tmp;
}
}
va_end(p_arg);
return max;
}