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

发布时间:2024年01月23日

前言

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

参考文章

题目和答案来自这篇文章:
【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的部分给舍去了。
文章来源:https://blog.csdn.net/zlllc/article/details/135727547
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。