((sizeof(n)+sizeof(int)-1)~(sizeof(int)-1))
一、問(wèn)題的提出
兩年之前我寫(xiě)過(guò)一篇可變參數(shù)學(xué)習(xí)筆記,里面曾經(jīng)簡(jiǎn)單的解釋過(guò)一句:
代碼
((sizeof(n)+sizeof(int)-1)&~(sizeof(int)-1))
的作用是在考慮字節(jié)對(duì)齊的因素下計(jì)算第一個(gè)可變參數(shù)的起始地址。
當(dāng)時(shí)限于時(shí)間和水平,未能做更詳細(xì)的解釋。
今天(2007-11-26)在csdn論壇上看到了一個(gè)帖子
http://topic.csdn.net/u/20071123/16/c8d17d3f-9f49-49af-a6d8-1d7a7d84dc1c.html?seed=303711257
問(wèn)題:CRT源碼分析中一個(gè)關(guān)于可變函數(shù)參數(shù)的問(wèn)題
提問(wèn)者:Sun_Moon_Stars
里面又問(wèn)到了這個(gè)宏,于是決定抽出半天時(shí)間,把這個(gè)問(wèn)題詳細(xì)的說(shuō)清楚。也算是把我的那篇文章
做一個(gè)完美的結(jié)尾。
二、引子
先看一個(gè)日常生活中的問(wèn)題,
問(wèn)題1:假設(shè)有要把一批貨物放到集裝箱里,貨物有12件,
一個(gè)箱子最多能裝6件貨物,求箱子的數(shù)目。
解答:顯然我們需要12/6=2個(gè)箱子,并且每個(gè)箱子都是滿(mǎn)的。這個(gè)連小學(xué)生都會(huì)算:-)
問(wèn)題2:?????? 把問(wèn)題1的條件改一下,假設(shè)一個(gè)箱子最多能裝5件貨物,那么現(xiàn)在的箱子數(shù)是多少?
解答:?????? 12/5=2.4個(gè),但是根據(jù)實(shí)際情況,箱子的個(gè)數(shù)必須為整數(shù),(有不知道這個(gè)常識(shí)的就不要再往下看了,
回小學(xué)重讀吧,呵呵)自然我們就要取3,
下面把問(wèn)題一般化
三、一般數(shù)學(xué)模型
問(wèn)題3:設(shè)一個(gè)箱子最多可以裝M件貨物,且現(xiàn)有N件貨物,
則至少需要多少個(gè)箱子,給出一般的計(jì)算公式。
這里要注意兩點(diǎn)
1、箱子的總數(shù)必須為整數(shù)
2、N不一定大于M,很顯然,即使N <M,也得需要一只箱子
四、通項(xiàng)公式
1、預(yù)備知識(shí)
在討論之問(wèn)題3的解答之前,我們先明確一下/運(yùn)算符的含義。
定義/運(yùn)算為取整運(yùn)算,即
對(duì)任意兩個(gè)整數(shù)N,M,必然有且只有唯一的整數(shù)X,滿(mǎn)足
X*M?? <=?? N?? <?? (X+1)*M,那么記N/M=X。
這個(gè)也正是c里/運(yùn)算的確切含義。x的存在性和唯一性的嚴(yán)格證明可以見(jiàn)數(shù)論教材。
以后如無(wú)額外說(shuō)明,/運(yùn)算的含義均和本處一致。
/運(yùn)算有一個(gè)基本的性質(zhì)
若N=MX+Y,則N/M=X+Y/M,證明略
注意:N不是可以隨便拆的,設(shè)N=A+B,那么一般情況下N/M?? 不一定等于?? A/M+B/M,
如果A和B至少有一個(gè)是M的倍數(shù),才能保證式子一定成立。
2、分步討論
根據(jù)上面的/運(yùn)算符的定義,我們可以得到問(wèn)題三的解答,分情況討論一下
已知N/M=X,那么當(dāng)
(1)、當(dāng)N正好是M的倍數(shù)時(shí)即N=M*X時(shí),那么箱子數(shù)就是X=N/M
(2)、如果N不是M的倍數(shù),即N=M*X+Y(1 <=Y <M)時(shí)
那么顯然還要多一個(gè)箱子來(lái)裝余下的Y件貨物,
則箱子總數(shù)為X+1?? =?? N/M+1
3、一般公式
上面的解答雖然完整,但是用起來(lái)并不方便,因?yàn)槊看味家ヅ袛郚和M的倍數(shù)關(guān)系,
我們自然就要想一個(gè)統(tǒng)一的公式,于是,下面的公式出現(xiàn)了
箱子數(shù)目為???? (N+M-1)/M
這個(gè)式子用具體數(shù)字去驗(yàn)證是很簡(jiǎn)單的,留給讀者去做。
我這里給一個(gè)完整的數(shù)學(xué)推導(dǎo):
現(xiàn)在已經(jīng)假定?? /運(yùn)算的結(jié)果為取整(或者說(shuō)取模),即
N/M=X,則XM?? <=N?? <(X+1)M
那么,
(1)、當(dāng)N=MX時(shí),(N+M-1)/M=?? MX/M+(M-1)/M=X
(2)、當(dāng)N=MX+Y(1 <=Y <M)時(shí),
由1 <=Y?? <?? M,同時(shí)加上M-1,得到M?? <=?? Y-1+M?? <=?? 2M-1?? <2M
根據(jù)?? /運(yùn)算的定義?? (Y-1+M)?? /M?? =?? 1
所以 (N+M-1)/M?? =?? (MX+Y+M-1)/M=?? MX/M+(Y+M-1)/M=?? X+1
顯然?? 公式?? (N+M-1)/M與2中的分步討論結(jié)果一致。
可能有的讀者還會(huì)問(wèn),這個(gè)公式是怎么想出來(lái)的,怎么就想到了加上那個(gè)M-1?
這個(gè)問(wèn)題可以先去看看數(shù)論中的余數(shù)理論。
五、對(duì)齊代碼的分析
有了上面的數(shù)學(xué)基礎(chǔ),我們?cè)賮?lái)看看開(kāi)頭所說(shuō)的對(duì)齊代碼的含義
((sizeof(n)+sizeof(int)-1)&~(sizeof(int)-1))
意義就很明顯了
這里。機(jī)器字長(zhǎng)度sizeof(int)相當(dāng)于箱子的容量M,變量的真實(shí)字節(jié)大小相于
貨物總數(shù)N,整個(gè)代碼就是求n所占的機(jī)器字?jǐn)?shù)目。
順便仔細(xì)的解釋一下
~(sizeof(int)-1))
這里用到了一個(gè)位運(yùn)算的技巧,即若M是2的冪,M=power(2,Y);
則N/M?? =? N>>Y? ,
另根據(jù)數(shù)論中的余數(shù)定理,
有N=M*X+Z(1 <?? =Z <? M)
而注意到這里的N,M,Z都是二進(jìn)制表示,所以把N的最右邊的Y位數(shù)字就是余數(shù)Z.
剩下的左邊數(shù)字就是模X.
而內(nèi)存對(duì)齊要計(jì)算的是占用的總字節(jié)數(shù)(相當(dāng)于箱子的最大容量),所以
總字節(jié)數(shù) = ( N/M)*M =( N>>Y)<<Y
注意,這里的右移和左移運(yùn)算并未相互抵消,最后的結(jié)果實(shí)際上是把N中的余數(shù)Z去掉(被清0),
而左邊模X得以保持不變。
而當(dāng)M = power(2,Y) 時(shí)
(N >>Y) << Y = (N?? &(~(M-1))也是一個(gè)恒等式(這個(gè)讀者也可以用數(shù)字驗(yàn)證),
所以,就得到我們前面看到的宏
((sizeof(n)+sizeof(int)-1)&~(sizeof(int)-1))
注意:
(1)這里最關(guān)鍵的一點(diǎn)就是M必須是2的冪(有人常常理解成2的倍數(shù)也可以,那是不對(duì)的),
否則上面的結(jié)論是不成立的
(2)?? ~(M-1)更專(zhuān)業(yè)的叫法就是掩碼(mask)。因?yàn)閿?shù)字和這個(gè)掩碼進(jìn)行與運(yùn)算后,數(shù)字的最右邊Y位的
數(shù)字被置0("掩抹"掉了).即掩碼最右邊的0有多少位,數(shù)字最右邊就有多少位被清0。
小結(jié):
1、字節(jié)對(duì)齊的數(shù)學(xué)本質(zhì)就是數(shù)論中的取模運(yùn)算。在計(jì)算機(jī)上的含義就是求出一個(gè)對(duì)象占用的機(jī)器字?jǐn)?shù)目。
2、在數(shù)學(xué)上看內(nèi)存計(jì)算的過(guò)程就是先右移再左移相同的位數(shù),以得到箱子的最大容量。
3、在c中/運(yùn)算可以用位運(yùn)算和掩碼來(lái)實(shí)現(xiàn)以加快速度(省掉了求位數(shù)的過(guò)程),前提是機(jī)器字長(zhǎng)度必須為2的冪。
——————————————————
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) – 1) & ~(sizeof(int) – 1)
[此問(wèn)題的推薦答案]
~是位取反的意思。
_INTSIZEOF(n)整個(gè)做的事情就是將n的長(zhǎng)度化為int長(zhǎng)度的整數(shù)倍。
比如n為5,二進(jìn)制就是101b,int長(zhǎng)度為4,二進(jìn)制為100b,那么n化為int長(zhǎng)度的整數(shù)倍就應(yīng)該為8。
~(sizeof(int) – 1) )就應(yīng)該為~(4-1)=~(00000011b)=11111100b,這樣任何數(shù)& ~(sizeof(int) – 1) )后最后兩位肯定為0,就肯定是4的整數(shù)倍了。
(sizeof(n) + sizeof(int) – 1)就是將大于4m但小于等于4(m+1)的數(shù)提高到大于等于4(m+1)但小于4(m+2),這樣再& ~(sizeof(int) – 1) )后就正好將原長(zhǎng)度補(bǔ)齊到4的倍數(shù)了。
?
轉(zhuǎn)載:https://blog.csdn.net/fulinus/article/details/8286252
總結(jié)
以上是生活随笔為你收集整理的((sizeof(n)+sizeof(int)-1)~(sizeof(int)-1))的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ARM的pll
- 下一篇: u-boot分析之makefile分析(