VC內存對齊準則(Memory alignment)

***************************************************

更多精彩,歡迎進入:http://shop115376623.taobao.com

***************************************************


本文所有內容在建立在一個前提下:使用VC編譯器。著重點在于:VC的內存對齊準則;同樣的數據, 不同的排列有不同的大小,另外在有虛函數或虛擬繼承情況下又有如何影響?

內存對齊?!What?Why?

對于一臺32位的機器來說如何才能發揮它的最佳存取效率呢?當然是每次都讀4字節(32bit)(一個字節8位,一次讀取4個字節,剛好滿負荷讀取), 這樣才可以讓它的bus處于最高效率。實際上它也是這么做的,即使你只需要一個字節,它也是 讀一個機器字長(這兒是32bit)。更重要的是,有的機器在存取或存儲數據的時候它要求數據 必須是對齊的,何謂對齊?它要求數據的地址從4的倍數開始,如若不然,它就報錯。還有的機 器它雖然不報錯,但對于一個類似int變量,假如它橫跨一個邊界的兩端,那么它將要進行兩次 讀取才能獲得這個int值。比方它存儲在地址為2~5的四個字節中,那么要讀取這個int,將要 進行兩次讀取,第一次讀取0~3四個字節,第二次讀取4~7四個字節。但是如果我們把這個整 形的起始地址調整到0,4,8…呢?一次存取就夠了!這種調整就是內存對齊了。我們也可以依次 類推到16位或64位的機器上。

邊界該如何調整

對于32位的機器來說,它當然最渴望它的數據的大小都是4 Byte或者4的倍數Byte,這樣它就能 最有效率的存取數據,當然如果數據小于4Byte,那也是沒問題的。那么編譯器要做的便是盡量滿 足這個要求。

這兩天我斷續對VC做了一些實驗,并總結如下三條準則,你要明白的是這并非來自微軟的官方文 檔,但我自以為這些準則或許不全但應該都是正確的:

  • 變量存放的起始位置2應為變量的大小與規定對齊量1中較小者的倍數。例如,假 設規定對齊量為4,那么char(1byte)變量應該存儲在偏移量為1的倍數的地方,而整形變 量(4byte)則是從偏移量為4的倍數的地方,而double(8 byte)也同樣應存儲在偏移量為 4的倍數的地方,為什么不是8?因為規定對齊量默認值為4,而4 < 8。在VC中默認對齊量 為8,而非4
  • 結構體整體的大小也應該對齊,對齊依照規定對齊量與最大數據成員兩者中較小的進行。
  • Vptr影響對齊而VbcPoint(Virtual base class pointer)不影響。

一個實例

對于類T:

class T{char c;int i;double  d;};

將其sizeof輸出后的大小為16,其內存布局如圖T.變量c從偏移量為0開始存儲,而整形i第一個 符號條件的偏移量為4,double型d的第一個符號條件的為8。整個對象的大小為16,不需要再進 行額外的對齊。

圖T(類T 的內存布局) :

同樣的數據,不同的大小

再看類L,它與T存儲同樣類型的數據,僅僅是順序不同罷了,那么它sizeof輸出的大小是多少呢?

類L:

class L{char c;double  d;int i;};

它sizeof后的結果或許會令你大吃一驚,或許不會(如果你有認真讀前面的兩條準則)。L sizeof后的結果是24!同樣是一個int,一個char,一個double卻整整多出了8個字節。這期間 發生了什么?我們依據前面兩條規則來看看。C存儲于0的位置,1~7都不能整除8,所以d存儲 在8~15,16給i正好合適,i存儲在16~19。總共花費了20個字節,抱歉不是8的倍數,還得補 齊4個。現在你可以看看圖L的關于類L的內存布局,再比較一下類L和類T的內存布局。

圖L(類L的布局)

我得出了這樣一條并不權威的結論,因為我還沒聽有人這樣說過:在聲明數據成員的時候,將 最大字節數的變量放在最前面3,切忌不要將大小差距很大的類型交替聲明。

Vptr影響對齊而VbcPoint(Virtual base class pointer)不影響

前面的實例只涉及前兩條準則,現在我們來看看第三條的兩個實例:

class X{char a;};
class Y: virtual public X{};

Y的大小為:a占一個字節,VbcPoint(我稱他為虛基類指針)占四個字節。我們不論a與VbcPoint 的位置如何擺放,如果將VbcPoint等同于一個成員數據來看的話,sizeof(Y)都應該為8.實際上 它是5!就我目前的水平,我只能先將其解釋為VbcPoint不參與對齊。

對于vptr這個問題則不存在:

class X{char a;virtual int vfc(){};}

sizeof(X)的大小確實為8.

關于#pragma pack(n)

用#pragma pack(n)改變規定對齊量試試眨眼


  1. 規定對齊量:實際上并沒有這么一個名詞,是我為了方便而造出來的。在VC中這個“規定對齊量”會有一個默認值,這個默認值一般為8,我原來一直以為這個值以為是4,至于它為什么為8,我現在還不知道。。我們也可以通過#pargma pack(n)來規定這個值,目前n可以為1,2,4,8,16。??

  2. 這個起始位置指的是相對于結構體(類)來說的。??

  3. 此處有一點問題,這個問題由獨酌逸醉提出,他認為將最小的數據放在最前面可能會更好,我們有進行過討論,但可惜的是由于在2011/11/24日數據庫丟失,我只能用備份還原,所以丟失了一些數據,無疑,本文的評論也在其中。不過我對這個問題映像深刻,因為我在寫這篇博客的時候便困惑于到底成員是應該放在之前還是之后,因為這兩種情況我都找不到強有力的理由來支撐它們。后來使我確信從大到小排列好于從小到大排列的理由在于,從大到小排列一般無需成員之間的對齊,唯一的對齊工作是最后進行的整個結構體對齊的工作。毫無疑問的是,這應該是最節省內存的方式。再之后,獨酌提出從小到大可能好些,雖然沒有給出有說服力的理由,但卻使我無比困惑,我當時雖然認為從大到小的排列更有優勢,但卻實在想不出一個實例能使得它優于從小到大排列的。不過最終我擊垮了自己的理由,在繼承狀況下從大到小排列很容易被打破,比方,基類的成員為一個char,繼承類的成員為double,int,char雖然基類和繼承類都是按從大到小的順序排列的,但是繼承類的內存布局最終會使char,double,int,char,此時既不能避免成員對齊,又導致后面的結構體對齊。暫時獲得的最終結果是從小到大排列是更好的一種排列方式。(2011/12/31增補)?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458948.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458948.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458948.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[redis設計與實現][7]基本數據結構——對象

Redis對基礎數據類型進行了封裝&#xff0c;構建出上層的對象系統&#xff0c;這個系統包含&#xff1a;字符串對象、列表對象、哈希對象、集合對象和有序集合對象。 Redis對象結構&#xff1a; [cce lang”c”] typedef struct redisObject { //類型 unsigned type:4; //編碼 …

Linux中samba的權限詳解,活用三種權限 理解Samba的權限控制

在企業內網開發環境方面&#xff0c;文件服務器是一個非常重要的環節。在這當中&#xff0c;Samba服務器由于其權限控制的高度靈活性&#xff0c;在這里撫琴煮酒會進行一些列詳細的說明。之前我們已經介紹了Samba服務器一些入門和基本的更換用戶、端口監聽、列表控制等技巧&…

安卓基礎01

安卓基礎01SDK System images 這是在創建模擬器時需要的system image&#xff0c;也就是在創建模擬器時CPU/ABI項需要選擇的&#xff0c;下載并解壓后&#xff0c;將解壓出的整個文件夾復制或者移動到 your sdk 路徑/system-images文件夾下即可&#xff0c; 如果沒有 system-im…

C++存儲區域基礎概念詳解

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 以下詳解來自&#xff1a; http://blog.163.com/zb_075/blog/static/3734032820115110…

創建、修改、刪除表總結

一、創建表 CREATE TABLE <表名> &#xff08;<列名><數據類型>[列級完整性約束條件] [&#xff0c;<列名> <數據類型>[列級完整性約束條件]] … [&#xff0c;表級完整性約束條件]&#xff09;&#xff1b; 如果完整性約束條件涉及到該表的多個…

linux 編譯查看鏈接庫詳情,Linux環境下的編譯,鏈接與庫的使用

鏈接參數控制鏈接器中提供了-dn -dy 參數來控制使用的是動態庫還是靜態庫&#xff0c;-dn表示后面使用的是靜態庫&#xff0c;-dy表示使用的是動態庫例:g -Lpath -Wl,-dn -lx -Wl,-dy -lpthread 這樣如果在path路徑下有libx.so和libx.a這個時候只會用到 libx.a.注意在最后的地…

在C++中用虛函數的作用是什么? 為什么要用到虛函數?

***************************************************更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com***************************************************虛函數聯系到多態&#xff0c;多態聯系到繼承。所以本文中都是在繼承層次上做文章。沒了繼…

mysql 主主互備實現

今天星期天&#xff0c;么事就寫個MYSQL的主主架構的博客&#xff0c;原理如下圖&#xff0c;不是我畫的網上找的。主機作用操作系統mysql版本對應IPvip數據庫mysqlA(主)centos6.4mysql 5.5.48192.168.48.129192.168.48.126mysqlB(備)centos6.4mysql 5.5.48192.168.48.132一&am…

Linux Deepin 版本大全,Deepin下載-Deepin linuxv20.0 官方版下載-6188手游網

Deepin linux安裝準備一&#xff1a;為 Deepin 留出硬盤空間以便安裝。1.打開磁盤管理(Windows 徽標上右鍵單擊&#xff0c;選擇磁盤管理)。2.選中一個分區(空閑空間大于 30G)&#xff0c;我選擇的是 C 盤&#xff0c;因為是固態硬盤所以安裝啟動會快很多。磁盤 1 的 200G 分區…

動手實踐 Linux VLAN - 每天5分鐘玩轉 OpenStack(13)

本節我們來看如何在實驗環境中實施和配置如下 VLAN 網絡 配置 VLAN 編輯 /etc/network/interfaces&#xff0c;配置 eth0.10、brvlan10、eth0.20 和 brvlan20。 下面用 vmdiff 展示了對 /etc/network/interfaces 的修改 重啟宿主機&#xff0c;ifconfig 各個網絡接口 用 brct…

Socket的3次握手鏈接與4次斷開握手

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 連接握手&#xff1a; 1.客戶端發送建立連接請求 &#xff08;發送請求&#xff09;2.…

Linux桌面需要強制訪問控制,RHCSA 系列(十三): 在 RHEL 7 中使用 SELinux 進行強制訪問控制...

RHCSA 認證&#xff1a;SELinux 精要和控制文件系統的訪問盡管作為第一級別的權限和訪問控制機制是必要的&#xff0c;但它們同樣有一些局限&#xff0c;而這些局限則可以由安全增強 Linux(Security Enhanced Linux&#xff0c;簡稱為 SELinux)來處理。這些局限的一種情形是&am…

使用canvas實現擦玻璃效果

體驗效果:http://hovertree.com/texiao/html5/25/效果圖&#xff1a;代碼如下&#xff1a; <!DOCTYPE html> <html> <head lang"zh"> <meta name"viewport" content"initial-scale1.0, maximum-scale1.0, user-scalableno, widt…

如何計算時間復雜度

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 求解算法的時間復雜度的具體步驟是&#xff1a; ⑴ 找出算法中的基本語句&#xff1b;…

linux顯示系統信息軟件下載,linux查看系統信息軟件安裝信息命令學習筆記

查看LINUX安裝版本[rootlocalhost etc]# unameLinux[rootlocalhost etc]# uname -aLinux localhost.localdomain 2.6.32-279.11.1.el6.i686 #1 SMP Tue Oct 16 14:40:53 UTC 2012 i686 i686 i386 GNU/Linux[rootlocalhost etc]# cat /proc/versionLinux version 2.6.32-279.11.…

Bzoj 2662: [BeiJing wc2012]凍結 dijkstra,堆,分層圖,最短路

2662: [BeiJing wc2012]凍結 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 647 Solved: 348[Submit][Status][Discuss]Description “我要成為魔法少女&#xff01;” “那么&#xff0c;以靈魂為代價&#xff0c;你希望得到什么&#xff1f;” “我要將有關魔法和奇…

[轉]opencv學習資料

轉自&#xff1a;http://blog.csdn.net/poem_qianmo/article/details/20537737 1&#xff1a;Mat imread(const string& filename, intflags1 ); eg: Mat image0imread("dota.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);//載入最真實的圖像 ge1i…

linux servlet 亂碼問題,Servlet一次亂碼排查后的總結

由來在寫一個小小的表單提交功能的時候&#xff0c;出現了亂碼&#xff0c;很奇怪request上來的參數全部是亂碼&#xff0c;而從數據庫查詢出來的中文顯示到頁面正常&#xff0c;鎖定肯定是request對象那里出了問題。后來經過排查&#xff0c;發現是我封裝的框架中出了問題&…

C/C++回調函數

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 對于很多初學者來說&#xff0c;往往覺得回調函數很神秘&#xff0c;很想知道回調函數…

Linux 命令[2]:mkdir

make directories mkdir -p [目錄名] -p 遞歸創建 [rootlocalhost ~]# mkdir -p test [rootlocalhost ~]# ls anaconda-ks.cfg install.log install.log.syslog test 當然只創建一個目錄 -p 是可以省略的 注&#xff1a;如果創建多級目錄沒有 -p 會報錯 如&#xff1a; [roo…