C语言 #define _INTSIZEOF(n)对齐的算法

1.  数学规则:
对于任意两个正整数 X, Y,假设Y>=X, 总是存在两个整数 q /*Quotient缩写*/, r /*Remainder缩写*/ 使得
等式 Y = q*X + r 成立, 要求 0 <= r < X, 则q(商), r(余数) 是唯一确定的。
商: q = [Y/X] /*[]:取整函数*/
余数: r = Y - q*X 推倒出 r = Y - [Y/X]*X.

2.  自定义规则:
    定义一种Y的取值规则,要求让Y是能整除X,且是最接近X的整数
    
2.1 地板法:
若 0 =< r < X, 取 Y = q*X, 
c语言为我们提供整形除法,所以地板法容易实现: q = Y/X /*取商*/, r = Y%X /*取余数*/
必杀技巧:如果X值恰巧是2^n,那么直接左移n位 q = Y >> n , r = Y&(X-1);

2.2 天花板法:
若 0 < r <= X, 取 Y = (q+1)*X. 

3.  现在我们问题是,如何利用C语言实现这个天花板法?
 Y     X   x/y   x%y    地板  天花板
 0 ->  5 -> 0 ->  0 ->   0 ->   5
 1 ->  5 -> 0 ->  1 ->   0 ->   5
 2 ->  5 -> 0 ->  2 ->   0 ->   5
 3 ->  5 -> 0 ->  3 ->   0 ->   5
 4 ->  5 -> 0 ->  4 ->   0 ->   5
 5 ->  5 -> 1 ->  0 ->   5 ->   5
 6 ->  5 -> 1 ->  1 ->   5 ->  10
 7 ->  5 -> 1 ->  2 ->   5 ->  10
 8 ->  5 -> 1 ->  3 ->   5 ->  10
 9 ->  5 -> 1 ->  4 ->   5 ->  10
10 ->  5 -> 2 ->  0 ->  10 ->  10
11 ->  5 -> 2 ->  1 ->  10 ->  15
12 ->  5 -> 2 ->  2 ->  10 ->  15
13 ->  5 -> 2 ->  3 ->  10 ->  15
14 ->  5 -> 2 ->  4 ->  10 ->  15
15 ->  5 -> 3 ->  0 ->  15 ->  15
16 ->  5 -> 3 ->  1 ->  15 ->  20
17 ->  5 -> 3 ->  2 ->  15 ->  20
18 ->  5 -> 3 ->  3 ->  15 ->  20
19 ->  5 -> 3 ->  4 ->  15 ->  20
20 ->  5 -> 4 ->  0 ->  20 ->  20
21 ->  5 -> 4 ->  1 ->  20 ->  25

直接让商Q = Y/X + 1行不行?
地板法:
Y = {0,1,2,3,4} => q = 0 则 Q = 1
Y = 5 => q = 1 则 Q = 2
很明显不是我们想要的结果,我们希望Y = 5,Q = 1
所以
商Q = (Y-1)/X + 1
Y=Q*X=((Y-1)/X + 1)*X = (Y+X-1)/X*X

4.证明过程:

ceiling的除法运算是只要余数不为0,商要进1,对于整型的Y/X而言只需Y+其最大的余数即可既ceiling = (Y+最大的余数)/X

4.1   证明方法1:
首先按照地板除Y/X,我们只能得到地板值,然后余数是r(从0到X-1),
现在我们要求用地板除规则实现天花板除,那么势必要给Y值的基础上加上X,再地板除(Y+X)/X,这样商能多加1,注意此时余数不发生改变,仍为(0,1,2...X-1)
但是天花板除法又规定,就是(Y+X)/X整除时,商不进位,那么我们让Y+X再减去1,即(Y+X-1)/X,则余数为(-1,0,1,2...X-2),原来余数为1的位置对应的数,现在整除了.也就是按照地板除规则,余数位(0,1,2...X-2),所对应的商都为0,至于-1对应的数,也就是原来能整除的数,已经去到上一轮了.

当Y=nX时,(Y+X-1)/X=>(nX+X-1)/X不进位,
当Y=nX+1时,(Y+X-1)/X=>(nX+1+X-1)/X=>n+1
...
当Y=nX+X-1时 (Y+X-1)/X=>(nX+X-1+X-1)/X=>n+1
当Y=nX+X时 (Y+X-1)/X=>(nX+X+X-1)/X=>n+1

4.2   证明方法2:
这也相当于把 Y 表示为:
Y = q'*X + r', 其中 -X < r' <=0                //最大非正剩余   
q'*X 是我们所求。

关键是如何用 c 语言计算它。由于我们能处理标准的带余除法,所以可以把这个式子转换成一个标准的带余除法,然后加以处理:
已知 Y = q'*X + r', 其中 -X < r' <=0 
则 Y+X = q'*X + (X+r'),其中 0 < X+r' <= X            //最asx大正剩余
则 Y+X-1 = q'*X + (X+r'-1), 其中 0 <= X+r'-1 <X    //最小非负剩余
所以 q'*X = [(Y+X-1)/X]*X 推倒出 q'*X = [(Y-1)/X]*X + X
其中 q' = [(Y+X-1)/X] 推倒出 q' = [(Y-1)/X] +1

5.用C语言计算(Y+X-1)/X*X

若 X 是 2 的方幂, 比如 2^m,则除为右移 m 位,乘为左移 m 位。
所以
(Y+X-1)/X : 相当于右移 m 位
(Y+X-1)/X*X : 相当于将上面的值再左移m位,也等价于将最低 m 个二进制位清0
上面两句等价于
(Y+X-1) & (~(X-1))
假设X = 8 = 0b1000,则 X-1 = 0b0111,~(X-1) = 0b111...11000
这样再与原来的值相与就清零了.

6.这种算法主要可以用到内存对齐上

如果数据总线是32根,那么每次只能取到4个字节的数据,可以使用该法方法,让地址总线每次都指向4的倍数的地址,


#define _INTSIZEOF(n) - ★行云流水★ - 博客园问:#define _INTSIZEOF(n)((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) 说能够在某些系统中内存对齐.(估计是得到一个2 或https://www.cnblogs.com/cmembd/p/3190706.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值