- 论坛徽章:
- 0
|
ACE_align_binary这个宏以前没怎么仔细看过,今天细看了一下不由得又对ACE的大牛们佩服不已了一番,
了解这个宏的朋友就不用浪费时间了,说得有什么不对的请大家指正.
原代码:
#define ACE_align_binary(ptr, alignment) \
((ptr + ((ptrdiff_t)((alignment)-1))) & (~((ptrdiff_t)((alignment)-1))))
先说问题:
一个字节流例如:101010101010101000011111111100111111100111110011010101011011
我们的类为了序列化的通用性,以某一字节对齐(以下讨论均假设为8位对齐),就是说
每8位or8×x位便是一个有意义的数据,比如 第0-7是一个有意义的单位,而1-9就没有意义,
也就是说读取数据必须从8的整数倍处开始,而数据指针可能由于种种原因可能不在8的整数倍上,
如何保证读取数据时一定是从8的整数位置开始的。
比如:
指针位于 0,则读取位置应该是0
指针位于 1,则读取位置应该是8
指针位于 2,则读取位置应该是8
... ...
指针位于 8,则读取位置应该是8
指针位于 9,则读取位置应该是16
指针位于 10,则读取位置应该是16
总结一下:
if (ptr==8n)ptr=ptr;
if(8n<ptr<8(n+1))ptr=8(n+1);
为了便于理解,在此写一个同样功能的函数(见笑)
char * my_align_binary(char * ptr,int alignment)
{
if(ptr%8==0)return ptr;
else return ptr+alignment - (ptr+alignment)%8
}
这个与原版的相比,差的实在是太远了
#define ACE_align_binary(ptr, alignment) \
((ptr + ((ptrdiff_t)((alignment)-1))) & (~((ptrdiff_t)((alignment)-1))))
这段代码的注释很详尽,但是做为一个chinese,我的e文也不怎么好,开始确实没怎么看懂,正所谓数读百遍,其义自见,一看就懂的朋友就不用在这里浪费时间了,看懂后不由得又对ACE的大牛们敬佩不已一番。
我们看一下这句话是怎么达到目的的,理解的关键在于 & (~((ptrdiff_t)((alignment)-1)))
注意alignment是2的n次方,二进制形式是..00..010..00..
设value=(ptr + ((ptrdiff_t)((alignment)-1)))
& (~((ptrdiff_t)((alignment)-1)))就是直接将value后面的尾数丢掉,假设alignment等于8,~(alignment)-1)意即
将value的后三位去掉,关键就在这里,8 二进制就是 1000 ,将后三位去掉,就是去掉模8的零头,变成8的整数倍
再看开始为什么要前进(alignment)-1步呢,
列举一下:
if (ptr==8n)前进(8-1)步然后去掉零头,还是ptr;
if(8n<ptr<8(n+1))前进(8-1)步,必然导致 8(n+1)<=ptr<8(n+2),然后去掉零头,得到8(n+1);
done!
看出来了吧,ACE_align_binary通过简单的加和与运算,完成的的确非常漂亮 |
|