可变参数列表(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这个指针指向未定义的地址。
首先,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这个指针指向未定义的地址。
相关文章推荐
- Android JS 与本地代码交互---JSBridge使用注意事项
- 单调递增子序列(二)
- iOS7隐藏状态栏 status Bar
- 学习网址记录
- CTP开发——下单
- 【Feature To Polygon】行政边界地图缺少某个面要素的生成方法
- 多线程同步:多窗口卖票
- 清除/设置默认Launcher
- EditText默认不弹出软件键盘
- C & C++的编译过程详解
- xcode archived issue:'Cordova/CDVViewController.h' file not found
- 网站飘窗js代码
- 如何联系苹果反馈问题
- 正则表达式
- 安卓开发中EditText的焦点改变处理(获取焦点和失去焦点交互变化)
- CSU 1537
- PHP中Http协议post请求参数
- Capture (采集)音频图像视频 基于ngcordova
- 数据库设计需要注意的问题
- 输入框手机号校验以及EditText的