[算法] 请使用宏定义实现字节对齐

前言

在网上看到这样一道题,不是很明白原理,记录一下。

参考文章

题目和答案来自这篇文章:
【C语言面试题】请使用宏定义实现字节对齐!】

题目

请使用C语言的宏定义实现一个功能,求得某个整型数M在N字节对齐的时,它的值大小。
 
说明:
1.M是一个非负整数;
2.N是2的整数倍,值可能是1,2,4,8,16等等。
 
要求:
1.不得使用除法(/);
2.不能使用函数实现,只能用宏实现;
3.自行设计测试用例,明确得出测试用例执行成功与否。

答案

#define GET_ALIGNED_2_POWER_NUM(num, n)		(((num) + (n) - 1) & (~((n) - 1)))	 

探究

题目的意思
求得某个整型数M在N字节对齐的时,它的值大小。
一开始我没懂这句话的意思,最开始我认为,一个int型,值为2,即使4字节对齐后,值不还是2吗?

但是实际上这里求的是,某个整型数M(指的是一个变量的size大小是M),按照N字节对齐后,占用的字节数。
例如一个int变量,占用4字节,
按照2字节对齐后,占用4字节‘
按照8字节对齐后,占用8字节;
按照16字节对齐后,占用16字节。

那么,答案中宏的计算,是什么意思呢
这里在重复一下参数的意思,num:需要对齐的数据的大小,n字节对齐的条件(N是2的整数倍)。

预期的对齐效果:
如果num小于n,那么最终结果就是按照n字节对齐。
例如数据大小为5字节,对齐条件是8字节,那么数据对齐后占用8字节。

如果num大于n,那么最终结果就是按照nm来进行对齐,m是使得 nm大于num的最小值。
例如数据大小为25字节,对齐条件是8字节,那么数据对齐后占用32(4 * 8)字节。

所以是不是,把num加上对齐条件n,然后把相加之和对n取余的余数舍去就行,例如 :

num==5, n==8,
5 + 8  = 13, 13 %8= 5, 输出13 - 5 = 8。

num==25, n==8,
25 + 8  = 33, 33 %8= 1, 输出33 - 1 = 32。

但是有个漏洞,如果num 和对齐条件相等呢,取余就没有余数,例如:

num==8, n==8,
8 + 8  = 16, 16 %8= 0, 输出16 - 0 = 16。(应该是8)

num==24, n==8,
24 + 8  = 32, 32 %8= 0, 输出32 - 0 = 32。(应该是24)

这里得出的值就比预期的值大了。

所以应该把num 加上 n - 1,然后把结果中,对n取余的余数舍去。例如:

num==5, n==8,
5 + (8  - 1) = 12, 12 %8= 4, 输出12 - 4 = 8。


num==25, n==8,
25 + 8  - 1 = 32, 32 %8= 0, 输出32 - 0 = 32。

如果num 小于n,那么num + n 还是2n;
如果num 大于n,那么num + n 大于2n
如果num 小于n,那么num + n - 1 还是小于2n;
如果num 大于n,那么num + n - 1,还是大于2n
所以是否进行n-1,对num == n以外的情况没有影响。

这就是上面宏做的工作:

(((num) + (n) - 1)  //把num 加上 n - 1
↓
(((num) + (n) - 1) & (~((n) - 1)))	 // & (~((n) - 1))) 就是把小于n的部分给舍去了。
  • 15
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值