stdarg.h(c标准库)
1 /*my_stdarg.h*/ 2 /* 3 * c允许定义可接受一个可变参数列表的函数。而且是自己定义的额外的函数。 4 * stdarg.h定义的宏。允许在任何时候从头到尾地便利一个附加参数列表。 5 * 在遇到每一个参数之前,必须知道它的类型,但在一个给定的调用发生之前,不必知道它的细节。 6 * 宏va_start,一个函数必须至少声明一个固定的参数。宏va_start引用了最后一个固定参数所以它能够对可变参数进行定位, 7 * 访问所有未命名的参数之前调用宏。对类型va_list ap初始化。 8 * 宏va_arg,每一次调用都会修改ap,每次调用这个宏展开的表达式的类型和值跟调用的下一个参数的相同。 9 * 第一次调用返回parmN后面的第一个参数。 10 * 宏va_end,一个函数在返回到它的调用者之前一定要调用va_end。 11 * stdarg.h声明了一种类型,定义了3个宏,这样就可以提前访问一个参数表,调用函数在编译时并不知道这个参数表中参数的数目和类型。 12 * 在...之前的那个参数起着特殊的作用,记作parmN。 13 * 声明类型va_list。 14 * 可重复使用。 15 * 16 * 17 * c标准定义,一个可变参数表在内存中占据了一个连续的字符数组; 18 * 后继的参数占据着字符数组更高为位。 19 * 一个参数占据的空间开始于2^N字节的整数倍的存储边界。 20 * 存储空间的大小是可以表示这个参数2^N字节的最小倍数。 21 * 存储空间留下的任何间隙总是在参数数据对象的开头或者结尾。 22 * 23 */ 24 25 #define _AUPBND 3/*在可变参数表内部确定存储边界的屏蔽宏,2^N-1*/ 26 #define _ADNBND 3/*确定存储空隙是否在一个参数数据对象的开端或者结尾的屏蔽宏,在尾处2^N-1,否则为0*/ 27 /*4倍数对齐,且结尾为开始出,则 3 0*/ 28 #ifndef MY_STDARG_H_ 29 #define MY_STDARG_H_ 30 /*保存一个指向下一个参数空间的起始位置的指针*/ 31 typedef char *va_list; 32 /* 33 * 通过增加va_list对象ap的内容来使它指向下一个参数空间的起始位置,然后再退回来指向当前参数的起始位置, 34 * 然后通过强制类型转换把这个指针值转换成为指定类型的指针,最后解引用这个指针以访问存储在数据对象中的值。 35 */ 36 #define va_arg(ap, T) (*(T *)(((ap) += _Bnd(T, _AUPBND)) - _Bnd(T, _ADNBND))) 37 /*占位符*/ 38 #define va_end(ap) (void)0 39 /*跳过已命名的参数,也就是最后一个固定参数,使用内部宏_Bnd把它的参数大小操作为2^N字节的一个倍数*/ 40 #define va_start(ap, A) (void)((ap) = (char *)&(A) + _Bnd(A, _AUPBND)) 41 #define _Bnd(X, bnd) (sizeof(X) + (bnd) &~ (bnd)) 42 #endif
1 /*my_stdarg.c*/ 2 #include <assert.h> 3 #include <stdio.h> 4 #include "my_stdarg.h" 5 6 typedef struct { 7 char c; 8 }cstruct; 9 10 static int tryit(const char *fmt, ...) 11 { 12 int ctr = 0; 13 va_list ap; 14 15 va_start(ap, fmt); 16 for(; *fmt; ++fmt) 17 switch(*fmt){ 18 case 'i': 19 assert(va_arg(ap, int) == ++ctr); 20 break; 21 case 'd': 22 assert(va_arg(ap, double) == ++ctr); 23 break; 24 case 'p': 25 assert(va_arg(ap, char *)[0] == ++ctr); 26 break; 27 case 's': 28 assert(va_arg(ap, cstruct).c == ++ctr); 29 } 30 va_end(ap); 31 return ctr; 32 } 33 int main(void) 34 { 35 cstruct x = {3}; 36 37 assert(tryit("iisdi", '\1', 2, x, 4.0, 5) == 5); 38 assert(tryit("") == 0); 39 assert(tryit("pdp", "\1", 2.0, "\3") == 3); 40 printf("sizeof(va_list) == %u\n", sizeof(va_list)); 41 puts("success testing stdary.h"); 42 return 0; 43 }
posted on 2013-07-04 22:59 kevin_kang 阅读(725) 评论(0) 收藏 举报
浙公网安备 33010602011771号