可变参数列表(2)

来源:互联网 发布:双手简谱制作软件 编辑:程序博客网 时间:2024/06/06 00:35

可变参数列表的4个宏解释:

首先,stdarg.h里定义了va_list:

typedef char *  va_list;   

说明va_list 是一个指针char * 类型 ,下面会用到。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

(1)_INTSIZEOF(n)

定义如下:

#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )   

这个实际上是求n的对齐字节数,即为sizeof(int)的整数倍。

例如:sizeof(n)等于4  sizeof(int)等于4  那么

( (sizeof(n) + sizeof(int) - 1) 等于 7

(sizeof(int) - 1) )     等于3     000000000000000000000000000000011

~(sizeof(int) - 1) )                    等于 -4  11111111 11111111 11111111 11111100

 ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) =4             相当于把7的最后两个二进制位置为0(0111(7)置为0100(4))

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )

这个宏把v的地址强制转换成va_list(char *)类型,然后加上v类型字节对齐的大小 赋值给ap 所以ap的值就是第一个固定参数后的第一个参数

例如:printf("%d",n);    //  "%d"是第一个参数,调用va_start就会把n的地址赋值给ap。

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )    //ap增加了,但是表达式的值却还是原来的值

这个宏很巧妙,巧妙在它的运算符上。 用va_arg(ap,t)赋值时得到的值就是ap所在地址 t类型的值,然后ap所保存的地址自动加t类型的长度。

相当于赋值后地址+1 。

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define va_end(ap)      ( ap = (va_list)0 )                          // (char * )0  避免出现野指针

这个宏是在最后使用的,将ap指针指向0地址,目的是避免ap这个指针指向未定义的地址。




2 0
原创粉丝点击