青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-145  評論-173  文章-70  trackbacks-0
現(xiàn)在的一些處理器,需要你的數(shù)據(jù)的內(nèi)存地址必須是對齊(align)的,即使不是必須,如果你對齊的話,運(yùn)行的速度也會得到提升。雖然對齊會產(chǎn)生的額外內(nèi)存空間,但相對于這個(gè)速度的提升來說,是值得的。

所謂對齊,就是地址必須能整除一個(gè)整數(shù),這個(gè)就是對齊參數(shù)(alignment value)。合法的取值范圍是1、2、4、6、16、……、8192。

怎樣對齊呢?編譯器幫你搞定。

怎樣設(shè)置編譯器的對齊方式呢?用#pragma pack( n )和__declspec(align(#))。

依據(jù)它倆,編譯器是咋工作的?這個(gè)就是接下來要說的了。

#include <stdio.h>
#pragma pack( 1 )
struct A
{             
    char a;
    short b;
    char c;
};

int main()
{
    printf("%d\n",sizeof(A));
    return 0;
}
 

OK,下面對這個(gè)代碼進(jìn)行詳細(xì)的分析。

 

用MSDN的話一言以蔽之:

“The alignment of a member (except the first one) will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.”

翻譯成中文,也就是:

“結(jié)構(gòu)體中的數(shù)據(jù)成員,除了第一個(gè)是始終放在最開始的地方,其它數(shù)據(jù)成員的地址必須是它本身大小或?qū)R參數(shù)兩者中較小的一個(gè)的倍數(shù)。”

 

P.S:注意上面所說的后面一句話,也就是說,結(jié)構(gòu)體的數(shù)據(jù)成員的地址必須是本身大小和對齊參數(shù)中較小的那一個(gè)。

 

 

(1)在pack為1的時(shí)候,對齊參數(shù)是1,那么我們對這個(gè)結(jié)構(gòu)體每一元素進(jìn)行分析。

 

char a;        //    第一個(gè)元素在[0]位置處

 short b; //short兩個(gè)字節(jié),地址是min(1,sizeof(short))的倍數(shù),即1的倍數(shù)[1~2]

 char c; // 地址應(yīng)該是min(1,sizeof(1))的倍數(shù),從而即為[3]

 

故在pack為1的時(shí)候,輸出的結(jié)果應(yīng)該是4([0~3]),其中所有的元素都填滿了。

 

 

(2)在pack為2的時(shí)候,同樣按照上面的方法,我們繼續(xù)來分析下。

Char a; //第一個(gè)占[0]位置。

Short b; //min(2,sizeof(short)),也就是必須為2的倍數(shù),從而[2~3]

Char c;//min(2,sizeof(char)),也就是位1,地址為[4]

因此最后占據(jù)的大小是[0],[2~3],[4],整個(gè)結(jié)構(gòu)體的大小size必須是2的倍數(shù),所以應(yīng)該是6(向上對齊至2的倍數(shù))

 

 

(3)在pack為4的時(shí)候,同上,得到的結(jié)果是

[0],[2~3],[4],因此也是6.

 

 

然后我們對上面的這個(gè)結(jié)構(gòu)體變換一下順序,可以得到。

 

struct B

{

         char a;

         char b;

         short c;

};

 

 

在#pragma pack(4)的情況下,輸出卻是4(注:上面的輸出時(shí)6)

解釋如下:

 

Char a;//占據(jù)一個(gè)字節(jié),地址為【0】

Char b;//地址應(yīng)該是min(4,sizeof(char)) = 1的倍數(shù),也就是地址為【1】

Short c; //地址應(yīng)該是min(4,sizeof(short)) = 2的倍數(shù),也就是【2~3】

故總體占據(jù)的是【0~3】的連續(xù)單元,也就是4.

 

 

至此,我們對#prgama pack(n)的用法和對應(yīng)的判定方法有了一個(gè)全新的認(rèn)識。



 

特別提出:
sizeof(ao.a )還是1,sizeof(ao.b )還是2。

 如果struct B中含有A的一個(gè)對象m_a,
struct B
{
   …
   A m_a;
   …
}
則這個(gè)m_a對齊參數(shù)是A中最大的數(shù)據(jù)類型的大小(這里是short的2)和n中較小者。如果這個(gè)對齊參數(shù)是B中最大的話,最后B的大小也會與這個(gè)對齊參數(shù)有關(guān)。


m_a的對齊參數(shù),由于是A的變量,所以采用A的對齊參數(shù),也就是應(yīng)該是A的最大元素個(gè)數(shù)和n中較小的值。而B的大小就要根據(jù)這個(gè)對齊參數(shù)來確定大小。


#include <iostream>
#include <stdlib.h>

#define NUM 1
using namespace std;

#pragma pack ( 16 )

typedef struct {
    int a;
    char b;
    double c;
}test;

struct B
{
    int a;
    test b;
};
int main()
{
    cout << "sizeof(int) = "<<sizeof(int) << endl;
    cout << "sizeof(char) = " << sizeof(char) << endl;
    cout << "sizeof(double) = " << sizeof(double) << endl;
    cout << sizeof(test)<< endl;
    cout << sizeof(B) << endl;
    system("PAUSE");
    return 0;
}

 

(1)在pack為1的時(shí)候,由于min中有一個(gè)為1,所以都是相鄰存放的。

Sizeof(test)就是int+char+double的大小之和,即13.

而對應(yīng)的sizeof(B)則是一個(gè)int和一個(gè)struct之和。Int占4B,而struct的對齊參數(shù)則是

Min(1,sizeof(max(A)),A中最大的元素師double類型的,也就是8,所以結(jié)果是min(1,8)=1,所以也是相鄰存放的,而sizeof(A)的結(jié)果是13,所以直接是13+4 = 17.

此時(shí),sizeof(B)的大小是17.

 

(2) 在pack為2的時(shí)候,此時(shí)min中有一個(gè)為2,對于test結(jié)構(gòu)體,它的大小是4+2+8=14,因?yàn)樵赿ouble的時(shí)候,min(2,8)=2,所以double類型的變量應(yīng)該是2的倍數(shù)的地址,造成了char類型處空出了一個(gè)字節(jié)??傮w就是14B。而對于B結(jié)構(gòu)體而言,一個(gè)int占據(jù)4B,然后結(jié)構(gòu)體的對齊參數(shù)采用min(2,max(A)),即min(2,8)= 2,由于是int,所以下一個(gè)地址是4,自然也是2的倍數(shù),于是還是相鄰存放。而A結(jié)構(gòu)體的大小時(shí)14,于是B結(jié)構(gòu)體的大小時(shí)14+4=18.

(3) 在pack為4的情況下。同樣可以得到。此時(shí)對于A結(jié)構(gòu)體的大小是4+4+8=16,因?yàn)閐ouble類型的必須是4的倍數(shù),造成了char變量要占4個(gè)地方(實(shí)際只占一個(gè),只是說這個(gè)地方空出來了3B),所以總體的大小為16.而同樣對于B結(jié)構(gòu)體,sizeof的結(jié)果是16+4 = 20,因?yàn)閷τ诶锩娴某蓡T要是min(4,8) = 4,而int恰好是4的倍數(shù),所以相鄰存放。于是就是16,20.

(4) 在pack為8的情況下(有所變化?。。。?,此時(shí)A結(jié)構(gòu)體的大小是16,分析方法和上面相同,但是對于結(jié)構(gòu)體B而言就有所區(qū)別,此時(shí)int還是4個(gè)字節(jié),但是對于成員test結(jié)構(gòu)體,它的對齊參數(shù)是min(8,max(A)) = min(8,sizeof(double) ) = 8也就是對齊參數(shù)是8,所以結(jié)構(gòu)體變量要從地址為8開始,此時(shí)int就空出來了4B,從而最后求大小的時(shí)候應(yīng)該是8+sizeof(A)= 8+16=24(最終測試結(jié)果如此)

(5)在pack為16的情況(以及以后的情況),結(jié)果是:A的大小為16B,而B的大小是24B。

 

 

總結(jié):

(1)       對于一個(gè)由簡單類型組成的結(jié)構(gòu)體,它的大小是由每一個(gè)成員變量的地址決定的。我們要按照定義的順序,分別求出來地址開始的地方。從地址為0開始,每一個(gè)變量都采取min(n,sizeof(x))//x表示該變量的類型;來確定起始地址是多少的倍數(shù),然后開始計(jì)數(shù),直到填滿該數(shù)據(jù)。最后求出來總的大小。而且在pack>=2的時(shí)候最終的大小需要時(shí)2的倍數(shù),有時(shí)候需要向上取大為2的倍數(shù)。而在pack為1的情況則不需要。

(2)       對于含有結(jié)構(gòu)體成員的結(jié)構(gòu)體,方法同上,只是在于對于結(jié)構(gòu)體變量的對齊參數(shù)取法需要說明,具體就是min(n,結(jié)構(gòu)體成員的最大元素的大小),就像上面的,結(jié)構(gòu)體B中含有A成員,所以對齊參數(shù)就是min(n,sizeof(double))的大小,然后按照這個(gè)做法來取地址。


P.S:注意這里是pack而不是package,否則編譯器會直接忽略#pragma package(),因?yàn)榧词拱l(fā)生錯(cuò)誤編譯器也會直接忽略,而我們還是會默認(rèn)認(rèn)為編譯器已經(jīng)當(dāng)做了字節(jié)按照n來處理。(某些博客上面的內(nèi)容很容易讓人誤解或者暈倒!)

以上代碼結(jié)果在Dev C++ , C-Free 5.0,VS 2010上均通過測試。

參考資料:

http://blog.csdn.net/whoismickey/archive/2009/03/28/4032155.aspx
posted on 2011-03-13 14:09 deercoder 閱讀(5171) 評論(2)  編輯 收藏 引用 所屬分類: C++

評論:
# re: 【內(nèi)存對齊(一)】#pragma pack的用法及大小的計(jì)算 2011-03-16 18:13 | Soli
還真顛覆了我以前的認(rèn)識!  回復(fù)  更多評論
  
# re: 【內(nèi)存對齊(一)】#pragma pack的用法及大小的計(jì)算 2011-03-16 19:32 | 劉暢
@Soli
呵呵,這個(gè)也是在經(jīng)歷了一次面試之后有感而進(jìn)一步研究的,以前的認(rèn)識確實(shí)比較膚淺。  回復(fù)  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            免费欧美在线| 国产精品久久久久久影视| 欧美顶级少妇做爰| 欧美色综合网| 精品51国产黑色丝袜高跟鞋| 日韩写真在线| 午夜精品国产更新| 欧美大胆人体视频| 亚洲一二三区精品| 久久这里只有精品视频首页| 欧美亚一区二区| 一区二区在线观看av| 中文国产一区| 免费成人高清| 亚洲午夜电影在线观看| 免费日本视频一区| 国产精品一卡二| 日韩视频免费在线| 久久久久久噜噜噜久久久精品 | 久久精品综合| 欧美日韩一区二区三区免费看| 国产午夜久久| 一本色道久久综合亚洲精品不| 久久久久久久激情视频| 亚洲免费成人av电影| 久久一二三四| 国产日韩欧美麻豆| 亚洲一区二区三区精品在线观看 | 亚洲国产精品视频一区| 欧美亚洲免费在线| 91久久久一线二线三线品牌| 亚洲一区二区三区色| 欧美成人午夜77777| 国产亚洲一区二区三区| 亚洲无吗在线| 最新日韩精品| 久久免费国产精品1| 国产精品久久久久久久午夜 | 91久久精品久久国产性色也91| 欧美在线观看网址综合| 国产精品久久久久毛片软件| 夜夜躁日日躁狠狠久久88av| 欧美jizz19hd性欧美| 欧美一区二区福利在线| 国产精品麻豆va在线播放| 一本色道久久88综合日韩精品| 欧美成人精品1314www| 久久99在线观看| 国产精品有限公司| 午夜精品久久久久久久99水蜜桃| 99国产麻豆精品| 欧美国产高潮xxxx1819| 亚洲激情影院| 欧美国产日韩一区二区三区| 久久免费黄色| 影院欧美亚洲| 免费成人美女女| 久久国产精品久久久久久久久久 | 亚洲电影免费观看高清完整版在线 | 国产精品永久免费| 翔田千里一区二区| 亚洲一区二区黄| 国产精品午夜电影| 欧美一级免费视频| 亚洲欧美日韩精品综合在线观看| 国产精品久久久久久妇女6080 | 欧美专区日韩视频| 国产一区二区三区在线观看视频 | 免费在线看成人av| 久久蜜桃av一区精品变态类天堂| 在线播放精品| 欧美成人精品一区二区三区| 免费在线观看日韩欧美| 亚洲人成网站777色婷婷| 亚洲国产精品尤物yw在线观看| 欧美freesex交免费视频| 亚洲日韩视频| 亚洲精品视频在线| 国产精品久久二区| 欧美诱惑福利视频| 久久久999精品| 在线视频国内自拍亚洲视频| 亚洲国产成人久久综合一区| 欧美日韩1区2区3区| 亚洲一区三区在线观看| 午夜激情亚洲| 在线观看日韩www视频免费| 欧美激情亚洲一区| 欧美日韩在线亚洲一区蜜芽| 午夜国产不卡在线观看视频| 欧美在线不卡| 亚洲国产日韩欧美在线动漫| 亚洲精品在线观看视频| 国产精品亚洲成人| 免费精品视频| 欧美精品一区二区三区在线播放| 亚洲欧美www| 欧美在线短视频| 亚洲三级色网| 一区二区三区免费看| 国产午夜精品视频免费不卡69堂| 欧美成人精品一区二区三区| 欧美日韩精品一区视频| 欧美与欧洲交xxxx免费观看| 久久精品99无色码中文字幕| 亚洲美女免费精品视频在线观看| 亚洲一区二区三区精品动漫| 精品av久久久久电影| 日韩视频在线一区| 国产亚洲欧美日韩一区二区| 欧美激情精品久久久久久变态| 欧美午夜精品伦理| 久久亚洲私人国产精品va媚药| 欧美高清在线一区二区| 欧美亚洲一区二区在线观看| 久久久精品午夜少妇| 中日韩美女免费视频网址在线观看| 性娇小13――14欧美| 亚洲理伦在线| 欧美在线视频导航| 亚洲手机成人高清视频| 久久精品99久久香蕉国产色戒| 宅男噜噜噜66一区二区66| 久久久高清一区二区三区| 一本色道婷婷久久欧美| 久久精品理论片| 亚洲欧美精品| 免费在线视频一区| 欧美在线视频网站| 欧美日韩成人在线播放| 久久综合影音| 国产精品视频大全| 亚洲电影在线观看| 国产日韩欧美制服另类| 日韩视频一区二区在线观看| 亚洲成人在线视频网站| 亚洲欧美偷拍卡通变态| 日韩视频不卡| 久久米奇亚洲| 欧美一二三视频| 欧美日韩国产不卡在线看| 欧美成人免费全部观看天天性色| 国产精品欧美日韩一区二区| 亚洲国产老妈| 狠狠色狠狠色综合系列| 亚洲一区二区视频在线观看| 日韩亚洲国产欧美| 久久精品99无色码中文字幕| 亚洲欧美久久久久一区二区三区| 欧美护士18xxxxhd| 男女视频一区二区| 国产亚洲综合在线| 亚洲专区一区| 亚洲欧美一级二级三级| 欧美日韩亚洲系列| 亚洲黑丝在线| 亚洲人成久久| 美女主播一区| 你懂的国产精品| 国外成人性视频| 亚洲综合欧美日韩| 亚洲欧美日韩一区在线| 欧美日韩在线不卡一区| 亚洲精品一区二区三| 亚洲日韩欧美视频一区| 欧美成人黑人xx视频免费观看| 麻豆精品在线视频| 极品av少妇一区二区| 久久成人亚洲| 久久躁日日躁aaaaxxxx| 国语自产精品视频在线看| 欧美伊人久久| 久久伊人亚洲| 在线不卡a资源高清| 久久久久.com| 免费看的黄色欧美网站| 亚洲国产精品成人va在线观看| 久久综合伊人77777| 欧美成人自拍视频| 亚洲东热激情| 欧美高清影院| 91久久一区二区| 99精品国产高清一区二区| 欧美日韩成人综合天天影院| 一本一本a久久| 午夜免费在线观看精品视频| 国产精品视频xxxx| 欧美在线视屏| 久久躁狠狠躁夜夜爽| 精品999日本| 欧美成人精品影院| 亚洲精品欧美在线| 亚洲欧美日韩精品久久| 国产日本欧美一区二区三区| 欧美一区二区三区喷汁尤物| 免费高清在线一区| 99精品热视频| 国产精品久久精品日日| 欧美一区日本一区韩国一区| 女主播福利一区|