C语言变参函数宏定义分析

在C语言变参函数中总是会用到下面几个宏:
0、#define  _ADNBND                (sizeof (acpi_native_int) - 1)
1、#define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))
2、#define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
3、#define va_end(ap)              (void) 0
4、#define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))  

C语言传递参数时是从右到左将参数逐个压栈,因此C语言里通过栈指针来访问参数。C语言在压参数入栈时是”机器字“的大小为最小单位的,也就是说参数的地址都是”字“对齐的。

1、分析 
#define _bnd(X, bnd) :
将该宏定义展开为如下形式:
(
(
(sizeof (X)) + (bnd)
(
~(bnd)
)
)
bnd一般取3(32位cpu)或7(64位cpu) 。以32位cpu为例: ~(bnd) = 0xfffffffc,该值相当于一个掩码,使任何数与它相与后的结果都是4的倍数,这也正好吻合32位cpu入栈时4字节对齐的特点; (sizeof (X)) + (bnd) = sizeof(X) + 3,保证了不管参数X实际占据几个字节,表达式除以4取整后的值总是大于等于参数X的实际大小。

2、分析 
#define va_arg(ap, T):
将该宏定义展开为如下形式:
(
*(T *)
(
(
(ap) += (_bnd (T, _AUPBND))
)
(
_bnd (T,_ADNBND)
)
)
)  
该宏的功能是:获得ap指向参数的值,并使ap指向下一个参数,T用来指明当前参数类型。
注意((ap) += (_bnd (T, _AUPBND))) 是被一对括号括起来的,然后才减去(_bnd (T, _ADNBND), 所以整个宏取得的值是ap当前指向的参数值,但是先给ap加了当前参数在字对齐后所占的字节数,使其指向了下一个参数。  

 3、分析
#define va_end(ap)
(void) 0  
可能是为了跟
va_start(ap, A)  成对出现,也有可能是为了保证函数返回时能正确的恢复栈。(有疑问?)  

 
4、分析#define va_start(ap, A)
  将该宏定义展开为如下形式:     
(void) 
(
(ap) =
(
(
(char *) &(A)
(
_bnd (A,_AUPBND)
)
)
)  
该宏的功能是:初始化参数指针ap,将函数参数A右边第一个可变参数的地址赋给ap。 A必须是一个参数的指针,所以可变参数类型函数至少要有一个普通的参数。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值