在<<STL源码剖析>>的空间配置一章的二级配置器中,有如下一段源代码,功能是将bytes上调至8的倍数。
enum{_ALIGN=8}; //小型区块的上调边界
private: static size_t ROUND_UP(size_t bytes){ return (((bytes)+_ALIGN-1)&~(_ALIGN-1)); }
这里的源码乍一看很难懂,但是十分高效,现在具体看一下实现原理。
这里8是2^3,二进制表示为00001000。前面的0先省略了,不影响分析。
_ALIGN-1:
00001000->00000111;
~_ALIGN-1:
00000111->11111000;
bytes+ALIGN-1:
x这里如果bytes是8的倍数,那么低3位全是0。
xxxxx000->xxxxx111
(bytes+ALIGN-1)&(~_ALIGN-1):
xxxxx111->xxxxx000
这里得到的是bytes本身。
如果bytes不是8的倍数呢?那么首先
8n<bytes<8(n+1)
我们要求的就是8(n+1)。
bytes用二进制表示,低三位不全为0,加上ALIGN-1会向第4位进位。此时将第三位清零,使用取反后相与,得到的就是8(n+1)。
这里的简单推导一下:
8n<bytes<8(n+1)
bytes=8n+p,p<8
p存在低3位,8n存在高三位,执行加法bytes+ALIGN-1,产生进位。
现在bytes=8(n+1)+p,清零后为8(n+1)。
这个问题还可以推广到将一个数字上调到2^n的倍数。因为2^n的低n位必定全是0,上面是实例n=3的情况。