stdarg.h

stdarg.h【stdarg.h】stdarg.h是C语言中C标準函式馆的头档案,stdarg是由standard(标準) arguments(参数)简化而来,主要目的为让函式能够接收可变参数 。C++的cstdarg头档案中也提供这样的功能;虽然与C的头档案是兼容的,但是也有冲突存在 。
可变参数函式(Variadic functions)是stdarg.h内容典型的套用,虽然也可以使用在其他由可变参数函式调用的函式(例如,vprintf) 。
基本介绍中文名:stdarg.h
类型:头档案
相关学科:C语言
属于:C标準函式馆
可变参数函式声明可变参数函式可变参数函式的参数数量是可变动的,它使用省略号来忽略之后的参数 。例如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, ...){/* ... */}在C的旧形式中可能会出现较省略的函式定义:long func();char a;double b;long func(a, b, c, ...){/* ... */}成员stdarg.h数据类型类型名称描述相容va_list用来保存宏va_arg与宏va_end所需信息C89stdarg.h宏巨集名称描述相容va_start使va_list指向起始的参数C89va_arg检索参数C89va_end释放va_listC89va_copy拷贝va_list的内容C99访问参数访问未命名的参数,首先必须在可变参数函式中声明va_list类型的变数 。调用va_start并传入两个参数:第一个参数为va_list类型的变数,第二个为省略号前最后一个有名字的参数的名称,接着每一调用va_arg就会返回下一个参数,va_arg的第一个参数为va_list,第二个参数为返回的类型 。最后va_end必须在函式返回前被va_list调用(va_list当作参数)(没有要求要读取完所有参数) 。C99提供额外的宏,va_copy,它能够複製va_list 。而va_copy(va2, va1)函式作用为拷贝va1到va2 。没有机制定义该怎幺判别传递到函式的参数量或者数据类型 。函式通常需要知道或确定它们变化的方法 。共通的惯例包含:使用printf或scanf类的格式化字串来嵌入明确指定的类型 。在可变参数最后的标记值(sentinel value) 。总数变数来指明可变参数的数量 。类型安全性有些C实现提供了对可变参数的扩展,允许编译器检查适当的格式化字串及标誌(sentinels)的使用 。如果没有这个扩充,编译器通常无从检查传入函式的未命名参数是否为所预期的类型 。因此,必须小心谨慎以确保正确性,因为不匹配的数据类型将导致未定义行为(Undefined behavior) 。例如,如果传递空指针,不能仅仅写入NULL(可能实际定义为0),还要转化为适当的指针类型 。另一个考虑是未命名参数的默认的类型提升 。float将会自动的被转换成double 。同样的,比int(整数)更小容量的参数数据类型将会被转换成int或者unsigned int 。函式所接收到的未命名参数必须提前考虑将会出现的数据类型提升 。举例#include <stdio.h>#include <stdarg.h>void printargs(int arg1, ...) /* 输出所有int类型的参数,直到-1结束 */{va_list ap;int i;va_start(ap, arg1);for (i = arg1; i != -1; i = va_arg(ap, int))printf("%d ", i);va_end(ap);putchar('\n');}int main(void){printargs(5, 2, 14, 84, 97, 15, 24, 48, -1);printargs(84, 51, -1);printargs(-1);printargs(1, -1);return 0;}这个程式产生输出:5 2 14 84 97 15 24 4884 511头档案POSIX定义所遗留下的头档案varargs.h,它早在C标準化前就已经开始使用了且提供类似stdarg.h的功能 。MSDN明确指出这一头档案已经过时,完全被stdarg.h取代 。这个头档案不属于ISO C的一部分 。档案定义在单一UNIX规範的第二个版本中 。由于varargs.h不属于标準C,所以不对其详细说明 。