您的位置:首页 > 其它

可变参数列表(2)

2015-11-02 14:08 239 查看
可变参数列表的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这个指针指向未定义的地址。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: