bytxl的专栏

得意之时谨记,一半命运还掌握在上帝手里;失意之时须知,一半命运还掌握在自己手里。...

c/c++不定参数函数

stdarg.h是C语言中C标准函数库的头文件,stdarg是由stdandard(标准) arguments(参数)简化而来,主要目的为让函数能够接收不定量参数。 C++的cstdarg头文件中也提供这样的机能;虽然与C的头文件是兼容的,但是也有冲突存在。
不定参数函数(Variadic functions)是stdarg.h内容典型的应用,虽然也可以使用在其他由不定参数函数调用的函数(例如,vprintf)。

声明不定参数函数
不定参数函数的参数数量是可变动的,它使用省略号来忽略之后的参数。例如printf函数一般。代表性的声明为:
int check(int a, double b, ...);
不定参数函数最少要有一个命名的参数,所以
char *wrong(...);
在C是不被允许的(在C++中,这样的声明是合理的)。在C,省略符号之前必须要有逗号;在C++,则没有这种强制要求。

定义不定参数函数
使用相同的语法来定义:
long func(char, double, int, ...);
 
long func(char a, double b, int c, ...)
{
    /* ... */
}
在旧形式可能会出现较省略的函数定义:
long func();
 
long func(a, b, c, ...)
    char a;
    double b;
{
    /* ... */
}

访问参数
访问未命名的参数,首先必须在不定参数函数中声明va_list型态的变数。调用va_start并传入两个参数:第一个参数为va_list型态的变数,第二个为函数最后一个参数的名称,接着每一调用va_arg就会回传下一个参数,va_arg的第一个参数为va_list,第二个参数为回传的型态。最后va_end必须在函数回传前被va_list呼叫(當作參數)。(沒有要求要讀取完所有參數)
C99提供額外的巨集,va_copy,它能够复制va_list。而va_copy(va2, va1)意思为拷贝va1到va2。
没有机制定义该怎么判别传递到函数的参数量或者型态。函数通常需要知道或确定它们变化的方法。共通的惯例包含:
使用printf或scanf类的格式化字符串来嵌入明确指定的型态。
在不定参数最后的标兵值(sentinel value)。
总数变数来指明不定参数的数量.  


类型安全性
有些C工具将C扩充允许编译器检查适当格式化字符串及标兵(sentinels)的使用。如果没有这个扩充,编译器通常无从检查传入函数的未命名参数是否为所预期的型态。因此,必须对点做出谨慎的正确性确认,型态没有吻合为未定义行为(Undefined behavior)。举个例,如果传入NULL指针,首先就是不能写入对应到适当指针型态但纯粹NULL的指针。再者考虑默认参数应用到未命名参数。float将会自动的被转换成double‧同样的比int(整数)更小容量的参数型态将会被转换成int或者unsigned int‧函数所接收到的未命名参数必须预期到会被转换型态。

例子
#include <stdarg.h>
#include <stdio.h>

int sum(int n,...)
{
int sum = 0;
va_list arg_ptr;
va_start(arg_ptr,n);
for(;n;--n)
{
sum = sum + va_arg(arg_ptr,int);
}
        va_end(arg_ptr);

 

return sum;
}

int main(int argc,const char* argv[])
{
printf("sum: %i\n",sum(3,1,2,3));
return 0;
}
阅读更多
个人分类: C/C++
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭