《STL源码剖析》之 ROUND_UP()实现原理详解

研究SGI STL的stl_clloc.h源代码中读到如下一段代码, 其中ROUND_UP()的作用是将非8倍数的整数上调到8的倍数。

其实现代码非常简单只有一行

(((bytes) +__ALIGN-1) & ~(__ALIGN - 1))

由于本人数学不是很好, 特将其实现原理及理解思路作简单解释, 方便自己以后理解及其它有需要的读者。  

// instead of enum { x = N }, but fewcompilers accept the former.
# ifndef__SUNPRO_CC
    enum {__ALIGN = 8};
    enum {__MAX_BYTES = 128};
    enum {__NFREELISTS = __MAX_BYTES/__ALIGN};
# endif
  static size_t ROUND_UP(size_t bytes) {
        return (((bytes) + __ALIGN-1) &~(__ALIGN - 1));
  }

如果对位运算不清楚的读者,建议可以先看看这篇文章:

C++位运算:http://www.cnblogs.com/flying_bat/archive/2008/06/17/1224178.html 

正文: 

阅读了上述网页文章,自己再动手在纸上展开画一下, 就会发现round_up的实现(数学)原理(以进制思维来理解)其实很简单和自然:

具体讲解如下:

1. round_up函式:    

enum {__ALIGN = 8};
  static size_t ROUND_UP(size_t bytes) {
        return (((bytes) + __ALIGN-1) &~(__ALIGN - 1)); 

2. C++ (~)符号的作用是对位取反 即 0001 0001 取反后为 1110 1110

3. round_up实现原理:

   以 bytes = 30为例:

   a. (30 + 7) = 37, 可以知道30的round_up为32, 给32加(8-1)的目的是让其(一定)大于32

   b.  这样的话,以十进制形式,37肯定可以表达为如下的形式:(x*8 + y),  并且可以肯定这个y的值小于8,上述37表达形式为:(32 + 5)

   c.   根据上述b步骤的形式,我们很自然的明白, 只要将 ((bytes) + 8-1) 转换为(x*8 + y)的形式后,然后再将y的值减去就达到目的了

   d.   总结上述思路,我们要做事情有两个,一是将 ((bytes) + 8-1) 转换为 (x*8 + y)的形式; 二是将(x*8 + y)中的y值清零

   e.   在十进制下,要完成上述任务,比较困难,而在二进制下,就非常好办

   f.   首先,将 ((bytes) + 8-1) 转换为(x*8 + y), 只要将 ((bytes) + 8-1)的值转为二进制,如以37为例,其二进制为: 00100101,这样写你可能看得还不是很直观,这样写 (00100)    (101), 这样就可以发现,第一个小括号里面的值就为(x*8), 第二个小括号里面的值就为(y);

       接下来,我们的目的就很简单的, 将第二个小括号里面的所有位置为0即可, 参考上述网页中的规则“非运算和与运算结合,可以确保将指定位 清0, 故 & ~(__ALIGN - 1)的目的就是将第二个小括号中的位清0.

      至此, 问题圆满解决。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值