• <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>
            隨筆-145  評論-173  文章-70  trackbacks-0

            上面講到了關(guān)于pack的內(nèi)存對齊和計算方法,這里繼續(xù)講實現(xiàn)內(nèi)存對齊的另一種方式:__declspec( align(#) )

            __declspec( align(#) )#pragma pack( n )有密切聯(lián)系。

            當(dāng)一個變量或結(jié)構(gòu)體同時受兩者影響時,前者的優(yōu)先級高。

            成員的地址決定于前者及后者,其要么是前者的倍數(shù),要么是后者的倍數(shù),要么是成員的大小的倍數(shù),取最小。

            結(jié)構(gòu)體最后的大小于前者有關(guān),其要么是前者的倍數(shù),要么是結(jié)構(gòu)體中最大偏移量的倍數(shù),取最大。

            要算出最后結(jié)果,必須知道兩者的值或缺省值。

             

            下面舉一個例子來詳細(xì)的分析:

            #include <stdio.h>

            #include 
            "stdafx.h"
            #include 
            <stdlib.h>
            //using namespace std;

            #pragma pack( push, 
            4 )

            __declspec( align(
            32) )struct D
            {
                
            int i1;
                
            double d1;
                
            int i2;
                
            int i3;
            };

            int main()
            {
                cout 
            << "sizeof(int) = "<<sizeof(int<< endl;
                cout 
            << "sizeof(char) = " << sizeof(char<< endl;
                cout 
            << "sizeof(double) = " << sizeof(double<< endl;
                cout 
            << sizeof(D) << endl;
                system(
            "PAUSE");
                
            return 0;
            }

             

            這段代碼在VS 2010中的運行結(jié)果是,sizeof(D)的大小為32,而在Dev C++C-Free 5.0以及gcc中的結(jié)果都似乎20。下面我們來著重講講關(guān)于__declspec( align(#) )的用法:

            正如前面所說的,當(dāng)有__declspec( align(#) )pack的時候,__declspec( align(#) )的優(yōu)先級要高些。所以對于上面這個例子,我們首先來計算出來每一個的大小。

             

            1.       成員的地址如何取?

            規(guī)則:成員的地址要取pack(n)__declspec( align(m) ),以及成員自身大小這三者之間的最小值,也就是,min(n,m,sizeof(成員變量類型)),那么我們可以對每一個結(jié)構(gòu)體的成員都進(jìn)行分析。

             

            第一個為int類型,占據(jù)4B,所以地址是[0~3].

            第二個為double類型,它的地址要根據(jù)min(4,32,sizeof(double))來判斷,所以應(yīng)該是4的倍數(shù),也就是相鄰著int類型的i1存放。地址是[4~11]

            第三個為int類型,占據(jù)4B,同樣應(yīng)該是4的倍數(shù),地址是[12~15].

            第四個為int類型,占據(jù)4B,地址為[16~19].

             

            從而總的地址是從[0~19]連續(xù)存放的20個字節(jié),那么是否sizeof(D)的大小就是20呢?

             

            經(jīng)過測試,我們可以看到,在VS 2010中,結(jié)果是32why

             

            這就要用__declspec( align(#) )來解釋了。也就是下面第二點的內(nèi)容。

             

            2.       結(jié)構(gòu)體最后的大小如何決定?

            規(guī)則:結(jié)構(gòu)體最后的大小與__declspec( align(m) )有關(guān),其要么是它的倍數(shù),要么是結(jié)構(gòu)體中最大偏移量的倍數(shù),取最大

             

            根據(jù)這個規(guī)則,這里align32,而結(jié)構(gòu)體中最大的是double類型,也就是應(yīng)該是max(32,8)=32,所以最后結(jié)構(gòu)體的大小應(yīng)該是32的倍數(shù),而明顯上面我們看到的實際大小是20B,從而需要擴(kuò)展到32B

             

            在這里,就體現(xiàn)了__declspec( align(m) )的強大作用!

             

            同樣的,為了體現(xiàn)該語句的作用,我們?nèi)サ暨@個語句,運用我們前面一節(jié)內(nèi)容的知識,來計算并測試sizeof(D),最終不論是在VS 2010還是Dev C++中,運行的結(jié)果都是上面我們所預(yù)測的20B

             

            OK,下面回到最后的疑問,也就是前面我們提出的,為何加入了__declspec( align(m) )語句之后,在DevC++VS 2010的結(jié)果不同?

             

            實際上,對于這些內(nèi)存對齊的處理,不同的編譯器可能采取不同的處理,就像前面一節(jié)中所說的,我將pack誤用為package,導(dǎo)致根本沒有達(dá)到按照我要求的字節(jié)對齊的目的,而且編譯器根本不提供任何警告信息。那么,這里合理的解釋是:Dev C++不支持這種用法。

             

            通過查閱資料,參照這篇文章【 SSE指令介紹及其CC++應(yīng)用 】(http://blog.csdn.net/delphihero/archive/2006/09/24/1270069.aspx),我們可以看到作者有這么一段話:

             

            接下來我舉一個例子來說明SSE的指令函數(shù)是如何使用的,必須要說明的是我以下的代碼都是在VC7.1的平臺上寫的,不保證對其它如Dev-C++Borland C++等開發(fā)平臺的完全兼容。

             

            這里要注意一下,我使用了__declspec(align(16))做為數(shù)組定義的修釋符,這表示該數(shù)組是以16字節(jié)為邊界對齊的,因為SSE指令只能支持這種格式的內(nèi)存數(shù)據(jù)。

              我們在這里看到了SSE算的強大,相信它會成為多媒體程序員手中用來對付無窮盡流媒體數(shù)據(jù)的一把利劍。我后面還會寫一些關(guān)于SSE算法更復(fù)雜應(yīng)用的文章,敬請關(guān)注,感謝您抽時間閱讀!

             

            從這篇文章我們可以看到,SSE指令集的情況下,在VC 7.1下才支持__declspec(align(16))這種用法,而對于其他平臺不一定有效。而前面我們使用的Dev C++以及C-Free,都是基于g++或者MinGW,不一定會支持這種方式,或者說,不一定按照這種內(nèi)存對齊的建議來做,也就造成了結(jié)果的不同。

             

             

            下面我們來繼續(xù)探討結(jié)構(gòu)體中有結(jié)構(gòu)體的情況。

             

            先看看下面這段代碼:

            #include <stdio.h>

            #include 
            "stdafx.h"
            #include 
            <stdlib.h>
            //using namespace std;

            #pragma pack( push, 
            4 )

            __declspec( align(
            32) )struct D
            {
                
            int i1;
                
            double d1;
                
            int i2;
                
            int i3;
            };

            __declspec( align(
            16) ) struct E
            {
                 
            int i1;
                 D m_d;
                 
            int i2;
            };

            int main()
            {
                cout 
            << "sizeof(int) = "<<sizeof(int<< endl;
                cout 
            << "sizeof(char) = " << sizeof(char<< endl;
                cout 
            << "sizeof(double) = " << sizeof(double<< endl;
                cout 
            << sizeof(D) << endl;
                cout 
            << sizeof(E) << endl;
                system(
            "PAUSE");
                
            return 0;
            }

             

            最后運行的結(jié)果是sizeof(E)96,為何會是這個結(jié)果呢?我們來詳細(xì)講解下。

             

            對于結(jié)構(gòu)體E,第一個元素為int類型,所以占據(jù)[0~3]地址單元。

            第二個元素是一個結(jié)構(gòu)體,該結(jié)構(gòu)體由于受上面__declspec( align(32) )的影響,優(yōu)先級高,所以起始地址是32的倍數(shù),而且大小為32B,從而應(yīng)該放置在[32~63]單元處。

            最后一個是int類型的變量,大小為4,所以應(yīng)該是4的倍數(shù),地址為[64~67]

             

            故結(jié)構(gòu)體E的大小應(yīng)該是從[0~67],占據(jù)68B,而由于前面還有限制__declspec( align(16) ),同時成員變量的最大偏移是sizeof(D)=32,所以我們最后這個結(jié)構(gòu)體的大小應(yīng)該是他們中最大值的倍數(shù),也就是32的倍數(shù),68向上取32的倍數(shù)應(yīng)該是96.故結(jié)果為96.

             

            最后仍然是上面平臺的問題,在Dev C++G++下面的結(jié)果不同,原因上面解釋了。


            MSDN:

            The sizeof value for any structure is the offset of the final member, plus that member's size, rounded up to the nearest multiple of the largest member alignment value or the whole structure alignment value, whichever is greater.

            中文:

            sizeof的結(jié)果都是結(jié)構(gòu)體中最后的一個成員變量加上它的大小,再加上一個填充容量(padding),這個填充大小是成員變量最大的一個對齊參數(shù)或整個結(jié)構(gòu)體的對齊參數(shù)的倍數(shù),取哪個決定于哪個對齊參數(shù)較大

             

            ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/dv_vclang/html/e4209cbb-5437-4b53-b3fe-ac264501d404.htm

            ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/dv_vclang/html/9cb63f58-658b-4425-ac47-af8eabfc5878.htm




            P.S.:上面是關(guān)于內(nèi)存對齊的研究,如有謬誤,歡迎指出!


            附參考資料和拓展:

            1. #pragma pack :http://blog.sina.com.cn/s/blog_492aa57901008y3h.html
            2. #pragma pack( n )和__declspec( align(#) ) 的偏移量計算方法: http://blog.csdn.net/whoismickey/archive/2009/03/28/4032155.aspx
            3. #pragma pack(push,1) (pop) :http://blog.csdn.net/jiang1013nan/archive/2009/11/25/4861248.aspx
            4. 關(guān)于pragma pack的用法(四) C++中的內(nèi)存對齊問題: http://www.shnenglu.com/xczhang/archive/2007/12/23/39396.html
            5. SSE指令介紹及其C、C++應(yīng)用:http://blog.csdn.net/delphihero/archive/2006/09/24/1270069.aspx
            6. c++中__declspec用法總結(jié): http://sealbird.javaeye.com/blog/855096

             


            posted on 2011-03-13 22:30 deercoder 閱讀(10031) 評論(5)  編輯 收藏 引用 所屬分類: C++

            評論:
            # re: 【內(nèi)存對齊(二)】__declspec( align(#) )的用法和大小計算 2011-03-14 00:21 | fazhang
            內(nèi)存對齊是在筆試題中才開始接觸的。   回復(fù)  更多評論
              
            # re: 【內(nèi)存對齊(二)】__declspec( align(#) )的用法和大小計算 2011-03-14 09:39 | 劉暢
            @fazhang
            是的,面試中也會出現(xiàn),這個是有感于我在一次面試中的經(jīng)歷來進(jìn)行深入研究的。  回復(fù)  更多評論
              
            # re: 【內(nèi)存對齊(二)】__declspec( align(#) )的用法和大小計算 2011-03-14 11:42 | Husiwa
            VS2008下驗證通過  回復(fù)  更多評論
              
            # re: 【內(nèi)存對齊(二)】__declspec( align(#) )的用法和大小計算 2011-03-14 12:19 | 劉暢
            @Husiwa
            嗯,VS的后續(xù)版本估計都會支持。不過VC 6.0還不支持。  回復(fù)  更多評論
              
            # re: 【內(nèi)存對齊(二)】__declspec( align(#) )的用法和大小計算 2012-02-23 23:06 | 游客
            成員的地址決定于前者及后者,其要么是前者的倍數(shù),要么是后者的倍數(shù),要么是成員的大小的倍數(shù),取最小。

            這個不太對。成員地址跟結(jié)構(gòu)提前的__declspec( align(#) )沒關(guān)系。

            另外,MSDN中說到__declspec(align( # )) can only increase alignment restrictions.所以__declspec(align( # ))是不可能和別的來取最小值,只可能往大的取  回復(fù)  更多評論
              
            国产福利电影一区二区三区,免费久久久久久久精 | 久久99精品久久久久久hb无码| 中文字幕精品无码久久久久久3D日动漫| 久久五月精品中文字幕| 久久婷婷五月综合色奶水99啪| 精品无码久久久久久午夜| 激情综合色综合久久综合| 久久成人国产精品免费软件| 大伊人青草狠狠久久| 中文字幕热久久久久久久| 精品久久久无码人妻中文字幕豆芽| .精品久久久麻豆国产精品| 久久伊人色| 成人亚洲欧美久久久久| 久久久久亚洲av无码专区导航| 热RE99久久精品国产66热| 精品无码久久久久久尤物| 亚洲午夜久久久影院| 大香网伊人久久综合网2020| 人妻无码中文久久久久专区| 精品久久国产一区二区三区香蕉| 久久棈精品久久久久久噜噜| 久久亚洲中文字幕精品一区四| 久久久久久亚洲Av无码精品专口| 亚洲国产成人精品久久久国产成人一区二区三区综 | 久久综合九色综合精品| 漂亮人妻被黑人久久精品| 亚洲人成无码www久久久| 久久香蕉一级毛片| 久久精品一本到99热免费| 欧美精品丝袜久久久中文字幕 | 久久久无码精品亚洲日韩按摩| 一级女性全黄久久生活片免费 | 欧美牲交A欧牲交aⅴ久久 | 久久精品视屏| 久久精品无码一区二区app| 91精品久久久久久无码| 国产精品久久新婚兰兰| 免费一级欧美大片久久网| 久久综合九色欧美综合狠狠| 久久久人妻精品无码一区|