可能大家已经注意到,printf函数不存在任何内建的方式来得知给定的参数数目。使用stdarg系列的宏的每个程序都有责任通过确立某种约定或惯例来标志参数列表的约束。这里的printf函数的第1个参数必须是一个格式字符串,通过检查这个字符串来得到其余参数的数目与类型。所以关键就是实现printf函数用以存取变长参数列表的机制。这种机制应该拥有以下特性:
(1)只需要知道函数的第1个参数的类型,就可以对其进行存取。
(2)一旦第n个参数被成功存取,第n+1个参数就可以在仅知道类型的情况下进行存取。
(3)按这种方式存取一个参数所需要的时间不应太多。
需要特别注意的是:逆向存取参数,或者随机存取参数,或者以任何非从头到尾的顺序方式存取参数,都是不必要的。进一步来说,既不必要检测参数列表是否结束,也不可能。
这些信息存储在一个类型为va_list的变量中。因此,声明一个名称为ap的类型为va_list的变量后,只需要给定ap与第1个参数的类型就可以确定第1个参数的值。
通过va_list存取一个参数之后,将更新va_list,指向参数列表中的下一个参数。
因为一个va_list中包括了存取全部参数的所有必要信息,所以一个函数g可以为它的参数创建一个va_list,然后把它传递给另一个函数。这样,这个函数就能够访问到函数g的参数。
【例20.26】演示使用stdarg.h编写的printf函数的例子。
#include <stdarg.h>int printf( const char *format, ... ){ int n; va_list ap; va_start( ap, format ); n = vprintf( format , ap); va_end(ap); return n; }
第二篇第13章的debug和error函数都是根据这个原理编制的,这里就不再举例验证了。