- 微信公众号:郑尔多斯
- 关注「郑尔多斯」公众号 ,回复「领取资源」,获取IT资源500G干货。
升职加薪、当上总经理、出任CEO、迎娶白富美、走上人生巅峰!想一想还有点小激动- 关注可了解更多的
Nginx
知识。任何问题或建议,请公众号留言;
关注公众号,有趣有内涵的文章第一时间送达!
在nginx
的代码中常常出现相似((sizeof(n)+sizeof(int)-1)&~(sizeof(int)-1))
的代码,这部分代码的做用是什么呢?本文分析一下它的神奇之处。
本文主要参考文章末尾的两个连接,并稍做整理。html
先看一个平常生活中的问题,
问题1:假设有要把一批货物放到集装箱里,货物有12件,
一个箱子最多能装6
件货物,求箱子的数目。
解答:显然咱们须要12 / 6 = 2
个箱子,而且每一个箱子都是满的。这个连小学生都会算:-)
问题2: 把问题1的条件改一下,假设一个箱子最多能装5
件货物,那么如今的箱子数是多少?
解答:12/5=2.4
个,可是根据实际状况,箱子的个数必须为整数,(有不知道这个常识的就不要再往下看了,回小学重读吧,哈哈)天然咱们就要取3
,
下面把问题通常化nginx
问题3:设一个箱子最多能够装M件货物,且现有N件货物,
则至少须要多少个箱子,给出通常的计算公式。
这里要注意两点
一、箱子的总数必须为整数
二、N
不必定大于M
,很显然,很显然,即便N ≤ M
,也须要一个箱子微信
一、预备知识
在讨论之问题3的解答以前,咱们先明确一下/
运算符的含义。
定义/
运算为取整运算,即
对任意两个整数N,M,必然有且只有惟一的整数X
,知足X * M <= N < (X + 1) * M
,那么记N / M=X
。
这个也正是c语言
里/
运算的确切含义。x的存在性和惟一性的严格证实能够见数论教材。
之后如无额外说明, / 运算的含义均和本处一致。
/ 运算有一个基本的性质
若N=MX+Y
,则N/M = X+Y/M
,证实略
注意:N
不是能够随便拆的,设N= A + B
,那么通常状况下N/M
不必定等于A/M + B / M
,若是A
和B
至少有一个是M
的倍数,才能保证式子必定成立。
二、分步讨论
根据上面的/
运算符的定义,咱们能够获得问题三的解答,分状况讨论一下
已知N/M=X
,那么当
(1)、当N
正好是M的倍数时即N=M*X
时,那么箱子数就是X=N/M
(2)、若是N
不是M
的倍数,即N=M*X+Y
(1 <=Y < M
那么显然还要多一个箱子来装余下的Y
件货物 ),则箱子总数为X+1 = N/M+1
三、通常公式
上面的解答虽然完整,可是用起来并不方便,由于每次都要去判断N和M的倍数关系,
咱们天然就要想一个统一的公式,因而,下面的公式出现了
箱子数目为 ( N + M - 1) / M
.
这个式子用具体数字去验证是很简单的,留给读者去作。
我这里给一个完整的数学推导:
如今已经假定/
运算的结果为取整(或者说取模),即N/M=X,则XM <= N <(X+1)M
那么,
(1)、当N=MX
时,(N+M-1)/M = MX/M + (M-1)/M = X
(2)、当N=MX+Y(1 <=Y < M)
时,
因为 1 <=Y < M
, 同时加上M-1
,获得 M <= Y + M - 1 < 2M-1 < 2M
根据 /
运算的定义 (Y + M - 1) / M = 1
因此 (N+M-1) / M = (MX+Y+M-1)/M= MX / M+(Y+M-1) / M= X+1
显然 公式 (N+M-1)/M
与2
中的分步讨论结果一致。
可能有的读者还会问,这个公式是怎么想出来的,怎么就想到了加上那个M-1
?
这个问题能够先去看看数论中的余数理论。app
5、对齐代码的分析
有了上面的数学基础,咱们再来看看开头所说的对齐代码的含义((sizeof(n)+sizeof(int)-1)&~(sizeof(int)-1))
意义就很明显了
这里。机器字长度sizeof(int)
至关于箱子的容量M
, 变量的真实字节 sizeof(n)
大小相于货物总数N,整个代码就是求n
所占的机器字数目。ui
顺便仔细的解释一下~(sizeof(int)-1))
这里用到了一个位运算的技巧,即若M
是2
的幂,M=power(2,Y)
;
则N / M = N >> Y
,另根据数论中的余数定理,有N=M*X+Z (1 < = Z < M)
而注意到这里的N,M,Z
都是二进制表示,因此把N
的最右边的Y
位数字就是余数Z
.
剩下的左边数字就是模X
.
而内存对齐要计算的是占用的总字节数(至关于箱子的最大容量),因此总字节数 = ( N / M) * M = ( N>>Y)
注意,这里的右移和左移运算并未相互抵消,最后的结果其实是把N中的余数Z去掉(被清0)。spa
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) – 1) & ~(sizeof(int) – 1)
[此问题的推荐答案]~
是位取反的意思。_INTSIZEOF(n)
整个作的事情就是将n
的长度化为int
长度的整数倍。
好比n
为5
,二进制就是101b
,int
长度为4
,二进制为100b
,那么n
化为int
长度的整数倍就应该为8
。~(sizeof(int) – 1) )
就应该为~(4-1)=~(00000011b)=11111100b
,这样任何数& ~(sizeof(int) – 1) )
后最后两位确定为0
,就确定是4
的整数倍了。(sizeof(n) + sizeof(int) – 1)
就是将大于4m
但小于等于4(m+1)
的数提升到大于等于4(m+1)
但小于4(m+2)
,这样再& ~(sizeof(int) – 1) )
后就正好将原长度补齐到4
的倍数了。.net
((sizeof(n)+sizeof(int)-1)&~(sizeof(int)-1))边界对齐
& ~(sizeof(int) - 1) )详解unix