• 关于一段地址对齐的位运算代码的解释


    http://blog.csdn.net/aihao1984/article/details/5953668这篇博文讲C的函数可变参数时,发现了以下用于做地址对齐的这段代码:

    #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) //为了满足需要内存对齐的系统

    这段代码做的事情就是,给定一个变量n,算出这个变量对齐到某个字长(整型的字节数)整数倍的字节数。这段代码有些难以理解。那么慢慢分析下吧。

    假设有一个地址n,要把n按m对齐,无非就是找到大于等于n且整除m的最小的那个数

    我们定义一个宏函数F,它计算n按m对齐的结果,则按照上段代码的逻辑,F定义为:

    #define F(n, m) (n+m-1)&~(m-1)

    这段代码如果不用这种按位与来写,其实可以这么写:

    #define F(n, m) (n+m-1)/m*m

    以上的做法正确性可以分情况证明:

    为了说明问题方便,由于计算机里的除法和严格的数学意义上的除法是不一样的,我们这里以"/"表示计算机里的除法,"%"表示严格的数学除法,"mod"表示取模运算。之后也遵循这个惯例,只是代码还是遵循计算机语言本身的规范。

    1.如果n是能整除m,那么对齐结果应该就是n,能得出F(n, m)的结果正确;

    2.如果n不能整除m,那么对齐结果应该是n - n mod m + m。由于n - n mod m + m能整除m,所以我们只需要证(n - n mod m + m)/m等于(n+m-1)/m。也即证

      0<= (n+m-1) - (n - n mod m + m) < m

    上面这个式子很显然。

    当我们再审视计算机里的除法"/"时,发现,实际上,对于整数x与y,有:

      x/y = (x - x mod y) % y

    设a=n+m-1,有

      (n+m-1)/m*m = a/m*m = (a - a mod m)%m*m = a - a mod m

    实际上,只要证

      a&~(m-1) = a - a mod m

    当然,这里的前提是,m是2的幂次(因为m是整型的字节数,即字长)。

    这里假设m=2^q。那么m的二进制表示一定是1后面跟q个0。m-1则为最后面q位为1,前面全为0,按位取反结果是后面q位为0,前面为1。

    由于m是2的幂次,故a mod m结果就是a的二进制表示的最后q位结果。而a按位与一个前面全为1后q位为0的二进制数,则正好就是减去了后q位,等同于减去a对m的余数。

    故得证。

  • 相关阅读:
    聊一聊-JAVA 泛型中的通配符 T,E,K,V,?
    leetcode刷到的大牛思路记录
    leetcode树有关题目随笔
    SpringMVC Controller介绍及常见注解
    一个方法团灭 6 道股票问题
    IDEA中Update resources和Update classes and resources、Redeploy、Restart server的区别
    动态规划规律总结
    mapPartitions
    RDD的依赖关系
    foreachPartition来写数据库
  • 原文地址:https://www.cnblogs.com/waytofall/p/4109514.html
Copyright © 2020-2023  润新知