日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

详解结构体、类等内存字节对齐

發(fā)布時(shí)間:2025/5/22 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解结构体、类等内存字节对齐 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? 先說個(gè)題外話:早些年我學(xué)C程序設(shè)計(jì)時(shí),寫過一段解釋硬盤MBR分區(qū)表的代碼,對(duì)著磁盤編輯器怎么看,怎么對(duì),可一執(zhí)行,結(jié)果就錯(cuò)了。當(dāng)時(shí)調(diào)試也不太會(huì),又根本沒聽過結(jié)構(gòu)體對(duì)齊這一說,所以,問題解決不了,好幾天都十分糾結(jié)。后來萬般無奈請(qǐng)教一個(gè)朋友,才獲悉可能是結(jié)構(gòu)體對(duì)齊的事,一查、一改,果真如此。

? ? 問題是解決了,可網(wǎng)上的資料多數(shù)只提到內(nèi)存對(duì)齊是如何做的,卻鮮有提及為什么這樣做(即使提,也相當(dāng)簡(jiǎn)單)。筆者是個(gè)超級(jí)健忘者,很難機(jī)械式的記住這些破規(guī)則,于是仔細(xì)想了想,總算明白了原因,這樣,這些對(duì)齊的規(guī)則也就不會(huì)再輕易忘記了。? ? ?

? ? 不光結(jié)構(gòu)體存在內(nèi)存對(duì)齊一說,類(對(duì)象)也如此,甚至于所有變量在內(nèi)存中的存儲(chǔ)也有對(duì)齊一說(只是這些對(duì)程序員是透明的,不需要關(guān)心)。實(shí)際上,這種對(duì)齊是為了在空間與復(fù)雜度上達(dá)到平衡的一種技術(shù)手段,簡(jiǎn)單的講,是為了在可接受的空間浪費(fèi)的前提下,盡可能的提高對(duì)相同運(yùn)算過程的最少(快)處理。先舉個(gè)例子:

? ? 假設(shè)機(jī)器字長(zhǎng)是32位的(即4字節(jié),下面示例均按此字長(zhǎng)),也就是說處理任何內(nèi)存中的數(shù)據(jù),其實(shí)都是按32位的單位進(jìn)行的。現(xiàn)在有2個(gè)變量:? ??

  • char?A;?
  • int?B;?
  • ? ? ?假設(shè)這2個(gè)變量是從內(nèi)存地址0開始分配的,如果不考慮對(duì)齊,應(yīng)該是這樣存儲(chǔ)的(見下圖,以intel上的little endian為例,為了形象,每16個(gè)字節(jié)分做一行,后同):

    ? ? 因?yàn)橛?jì)算機(jī)的字長(zhǎng)是4字節(jié)的,所以在處理變量A與B時(shí)的過程可能大致為:

    ? ? A:將0x00-0x03共32位讀入寄存器,再通過左移24位再右移24位運(yùn)算得到a的值(或與0x000000FF做與運(yùn)算)

    ? ? B:將0x00-0x03這32位讀入寄存器,通過位運(yùn)算得到低24位的值;再將0x04-0x07這32位讀入寄存器,通過位運(yùn)算得到高8位的值;再與最先得到的24位做位運(yùn)算,才可得到整個(gè)32位的值。

    ? ? 上面敘述可知,對(duì)a的處理是最簡(jiǎn)處理,可對(duì)b的處理,本身是個(gè)32位數(shù),處理的時(shí)候卻得折成2部分,之后再合并,效率上就有些低了。

    ? ? 想解決這個(gè)問題,就需要付出幾個(gè)字節(jié)浪費(fèi)的代價(jià),改為下圖的分配方式:

    ? ? 按上面的分配方式,A的處理過程不變;B卻簡(jiǎn)單得多了:只需將0x04-0x07這32位讀入寄存器就OK了。

    ? ? 我們可以具體談結(jié)構(gòu)體或類成員的對(duì)齊了:

    ? ? 結(jié)構(gòu)體在編譯成機(jī)器代碼后,其實(shí)就沒有本身的集合概念了,而類,實(shí)際上是個(gè)加強(qiáng)版的結(jié)構(gòu)體,類的對(duì)象在實(shí)例化時(shí),內(nèi)存中申請(qǐng)的就是一些變量的空間集合(類似于結(jié)構(gòu)體,同時(shí)也不包含函數(shù)指針)。這些集合中的每個(gè)變量,在使用中,都需要涉及上述的加工原則,自然也就需要在效率與空間之間做出權(quán)衡。

    ? ? 為了便捷加工連續(xù)多個(gè)相同類型原始變量,同時(shí)簡(jiǎn)化原始變量尋址,再匯總上述最少處理原則,通常可以將原始變量的長(zhǎng)度做為針對(duì)此變量的分配單位,比如內(nèi)存可用64個(gè)單元,如果某原始變量長(zhǎng)度為8字節(jié),即使機(jī)器字長(zhǎng)為4字節(jié),分配的時(shí)候也以8字節(jié)對(duì)齊(看似IO次數(shù)是相同的),這樣,尋址、分配時(shí),均可以按每8字節(jié)為單位進(jìn)行,簡(jiǎn)化了操作,也可以更高效。

    ? ? 系統(tǒng)默認(rèn)的對(duì)齊規(guī)則,追求的至少兩點(diǎn):1、變量的最高效加工 2、達(dá)到目的1的最少空間?

    ? ? 舉個(gè)例子,一個(gè)結(jié)構(gòu)體如下:
    ?

  • //by www.datahf.net zhangyu
  • typedef?struct?T
  • {?
  • ????char?c; //本身長(zhǎng)度1字節(jié)?
  • ????__int64?d;? //本身長(zhǎng)度8字節(jié)
  • ????int?e;? //本身長(zhǎng)度4字節(jié)
  • ????short f;? //本身長(zhǎng)度2字節(jié)
  • ????char?g;? //本身長(zhǎng)度1字節(jié)
  • ????short?h;? //本身長(zhǎng)度2字節(jié)
  • };?
  • ? ? 假設(shè)定義了一個(gè)結(jié)構(gòu)體變量C,在內(nèi)存中分配到了0x00的位置,顯然:

    ? ? 對(duì)于成員C.c ?無論如何,也是一次寄存器讀入,所以先占一個(gè)字節(jié)。

    ? ? 對(duì)于成員C.d ?是個(gè)64位的變量,如果緊跟著C.c存儲(chǔ),則讀入寄存器至少需要3次,為了實(shí)現(xiàn)最少的2次讀入,至少需要以4字節(jié)對(duì)齊;同時(shí)對(duì)于8字節(jié)的原始變量,為了在尋址單位上統(tǒng)一,則需要按8字節(jié)對(duì)齊,所以,應(yīng)該分配到0x08-0xF的位置。

    ? ? 對(duì)于成員C.e ?是個(gè)32位的變量,自然只需滿足分配起始為整數(shù)個(gè)32位即可,所以分配至0x10-0x13。

    ? ? 對(duì)于成員C.f ?是個(gè)16位的變量,直接分配在0x14-0x16上,這樣,反正只需一次讀入寄存器后加工,邊界也與16位對(duì)齊。

    ? ? 對(duì)于成員C.g ?是個(gè)8位的變量,本身也得一次讀入寄存器后加工,同時(shí)對(duì)于1個(gè)字節(jié)的變量,存儲(chǔ)在任何字節(jié)開始都是對(duì)齊,所以,分配到0x17的位置。

    ? ? 對(duì)于成員C.h ?是個(gè)16位的變量,為了保證與16位邊界對(duì)齊,所以,分配到0x18-0x1A的位置。

    ? ? 分配圖如下(還不正確,耐心讀下去):

    ? ? 結(jié)構(gòu)體C的占用空間到h結(jié)束就可以了嗎?我們找個(gè)示例:如果定義一個(gè)結(jié)構(gòu)體數(shù)組 CA[2],按變量分配的原則,這2個(gè)結(jié)構(gòu)體應(yīng)該是在內(nèi)存中連續(xù)存儲(chǔ)的,分配應(yīng)該如下圖:
    ?

    ? ? 分析一下上圖,明顯可知,CA[1]的很多成員都不再對(duì)齊了,究其原因,是結(jié)構(gòu)體的開始邊界不對(duì)齊。

    ? ? 那結(jié)構(gòu)體的開始偏移滿足什么條件才可以使其成員全部對(duì)齊呢。想一想就明白了:很簡(jiǎn)單,保證結(jié)構(gòu)體長(zhǎng)度是原始成員最長(zhǎng)分配的整數(shù)倍即可。
    ? ? 上述結(jié)構(gòu)體應(yīng)該按最長(zhǎng)的.d成員對(duì)齊,即與8字節(jié)對(duì)齊,這樣正確的分配圖如下:

    ? ? 當(dāng)然結(jié)構(gòu)體T的長(zhǎng)度:sizeof(T)==0x20;

    ? ? ?再舉個(gè)例子,看看在默認(rèn)對(duì)齊規(guī)則下,各結(jié)構(gòu)體成員的對(duì)齊規(guī)則:
    ?

  • //by www.datahf.net zhangyu
  • typedef?struct?A?
  • {?
  • ????char?c;? //1個(gè)字節(jié)
  • ????int?d;? //4個(gè)字節(jié),要與4字節(jié)對(duì)齊,所以分配至第4個(gè)字節(jié)處
  • ????short?e;? //2個(gè)字節(jié), 上述兩個(gè)成員過后,本身就是與2對(duì)齊的,所以之前無填充
  • ?}; //整個(gè)結(jié)構(gòu)體,最長(zhǎng)的成員為4個(gè)字節(jié),需要總長(zhǎng)度與4字節(jié)對(duì)齊,所以, sizeof(A)==12?
  • typedef?struct?B?
  • {?
  • ????char?c;? //1個(gè)字節(jié)
  • ????__int64?d;? //8個(gè)字節(jié),位置要與8字節(jié)對(duì)齊,所以分配到第8個(gè)字節(jié)處
  • ????int?e;? //4個(gè)字節(jié),成員d結(jié)束于15字節(jié),緊跟的16字節(jié)對(duì)齊于4字節(jié),所以分配到16-19
  • ????short?f;? //2個(gè)字節(jié),成員e結(jié)束于19字節(jié),緊跟的20字節(jié)對(duì)齊于2字節(jié),所以分配到20-21
  • ????A?g;? //結(jié)構(gòu)體長(zhǎng)為12字節(jié),最長(zhǎng)成員為4字節(jié),需按4字節(jié)對(duì)齊,所以前面跳過2個(gè)字節(jié),
  • //到24-35字節(jié)處
  • ????char?h;? //1個(gè)字節(jié),分配到36字節(jié)處
  • ????int?i;? //4個(gè)字節(jié),要對(duì)齊4字節(jié),跳過3字節(jié),分配到40-43 字節(jié)
  • };?//整個(gè)結(jié)構(gòu)體的最大分配成員為8字節(jié),所以結(jié)構(gòu)體后面加5字節(jié)填充,被到48字節(jié)。故:
  • //sizeof(B)==48;
  • ? ? 具體的分配圖如下:

    ?

    ?上述全部測(cè)試代碼如下:

    ?

  • //by www.datahf.net zhangyu
  • #include?"stdio.h"?
  • typedef?struct?A?
  • {?
  • ????char?c;?
  • ????int?d;?
  • ????short?e;?
  • ?
  • };?
  • typedef?struct?B?
  • {?
  • ????char?c;?
  • ????__int64?d;?
  • ????int?e;?
  • ????short?f;?
  • ????A?g;?
  • ????char?h;?
  • ????int?i;?
  • };?
  • typedef?struct?C?
  • {?
  • ????char?c;?
  • ????__int64?d;?
  • ????int?e;?
  • ????short?f;?
  • ????char?g;?
  • ????short?h;?
  • };?
  • typedef?struct?D?
  • {?
  • ????char?a;?
  • ????short?b;?
  • ????char?c;?
  • };?
  • int?main()?
  • {?
  • ?
  • ????B?*b=new?B;?
  • ????void?*s[32];?
  • ????s[0]=b;?
  • ????s[1]=&b->c;?
  • ????s[2]=&b->d;?
  • ????s[3]=&b->e;?
  • ????s[4]=&b->f;?
  • ????s[5]=&b->g;?
  • ????s[6]=&b->h;?
  • ????s[7]=&b->g.c;?
  • ????s[8]=&b->g.d;?
  • ????s[9]=&b->g.e;?
  • ????s[10]=&b->i;?
  • ????b->c=?0x11;?
  • ????b->d=?0x2222222222222222;?
  • ????b->e=?0x33333333;?
  • ????b->f=0x4444;?
  • ????b->g.c=0x50;?
  • ????b->g.d=0x51515151;?
  • ????b->g.e=0x5252;?
  • ????b->h=0x66;?
  • ????int?i1=sizeof(A);?
  • ????int?i2=sizeof(B);?
  • ????int?i3=sizeof(C);?
  • ????int?i4=sizeof(D);?
  • ????printf("i1:%d\ni2:%d\ni3:%d\ni4:%d\n",i1,i2,i3,i4);//12?48?32?6?
  • }?
  • 運(yùn)行時(shí)的內(nèi)存情況如下圖:

    ?

    最后,簡(jiǎn)單加工一下轉(zhuǎn)載過來的內(nèi)存對(duì)齊正式原則:

    ?

    ? 先介紹四個(gè)概念:

    1)數(shù)據(jù)類型自身的對(duì)齊值:基本數(shù)據(jù)類型的自身對(duì)齊值,等于sizeof(基本數(shù)據(jù)類型)。

    2)指定對(duì)齊值:#pragma pack (value)時(shí)的指定對(duì)齊值value。

    3)結(jié)構(gòu)體或者類的自身對(duì)齊值:其成員中自身對(duì)齊值最大的那個(gè)值。

    4)數(shù)據(jù)成員、結(jié)構(gòu)體和類的有效對(duì)齊值:自身對(duì)齊值和指定對(duì)齊值中較小的那個(gè)值。

    ? 有效對(duì)齊值N是最終用來決定數(shù)據(jù)存放地址方式的值,最重要。有效對(duì)齊N,就是表示“對(duì)齊在N上”,也就是說該數(shù)據(jù)的"存放起始地址%N=0".而數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)變量都是按定義的先后順序來排放的。第一個(gè)數(shù)據(jù)變量的起始地址就是 數(shù)據(jù)結(jié)構(gòu)的起始地址。結(jié)構(gòu)體的成員變量要對(duì)齊排放,結(jié)構(gòu)體本身也要根據(jù)自身的有效對(duì)齊值圓整(就是結(jié)構(gòu)體成員變量占用總長(zhǎng)度需要是對(duì)結(jié)構(gòu)體有效對(duì)齊值的整 數(shù)倍)

    ?

    #pragma pack (value)來告訴編譯器,使用我們指定的對(duì)齊值來取代缺省的。

    如#pragma pack (1)??/*指定按2字節(jié)對(duì)齊*/

    #pragma?pack () /*取消指定對(duì)齊,恢復(fù)缺省對(duì)齊*/

    ?

    ?

    總結(jié)

    以上是生活随笔為你收集整理的详解结构体、类等内存字节对齐的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 成年人的天堂 | 久久久久无码国产精品不卡 | 免费香蕉视频 | 国产欧美日韩一区 | 国产又大又黑又粗免费视频 | 国产区在线 | a级片一区二区 | 亚洲精品在线视频免费观看 | 免费在线观看黄网站 | 亚洲欲妇 | 四虎影视最新网址 | 日韩av女优在线观看 | 亚洲国产精品成人综合 | 黄色免费片 | 韩国日本在线观看 | bl无遮挡高h动漫 | 欧美亚洲韩国 | 国产第一页视频 | 51精品国产人成在线观看 | 青青草原国产视频 | 久草91| 性xxxxxxxxx18欧美 | 亚洲精品乱码久久久久久久 | 91精品国产一区二区三区香蕉 | 极品色影视 | 日本一区二区在线看 | avxx| 伊人久久伊人 | 成人在线免费高清视频 | 久草这里只有精品 | av二区在线 | 免费在线看污 | 一级黄色美女视频 | 青青草视频在线看 | 911精品 | 精品视频在线观看一区二区 | av在哪里看 | av爽妇网| 青青成人网 | 免费国产精品视频 | 天天爽夜夜春 | 777精品久无码人妻蜜桃 | 嫩色av | 国产精品一区二区黑人巨大 | 成人午夜大片 | 久久av一区二区三区 | a资源在线观看 | av官网在线 | 一级片特黄 | 国产毛片久久 | 国产小视频在线免费观看 | xxx视频在线观看 | 欧美成人免费高清视频 | 影音先锋成人资源网 | 午夜动态图 | gai免费观看网站外网 | 欧美日韩精品一区二区 | 欧美精品久久久久性色 | 久久人人精品 | 奇米影视亚洲春色 | 老司机在线观看视频 | 国产成人综合久久 | 国产视频一区二区在线播放 | 91极品国产 | 国语对白永久免费 | 日韩在线视频观看免费 | 欧美毛片视频 | 超碰首页| 亚洲女人被黑人巨大进入 | 69一区二区 | 牛牛电影国产一区二区 | 人人九九 | 国内激情视频 | 最近最新中文字幕 | 亚洲性图av| 日本污网站 | 亚洲av综合色区无码一区 | 伊人久久五月 | 蜜桃91麻豆精品一二三区 | 欧美另类videossexo高潮 | 欧美怡红院 | 欧美成人精精品一区二区频 | 亚洲日批| 国产精品亚洲视频 | 欧美大片xxx| 性色综合| 国产精品毛片一区二区在线看 | 国产综合在线观看 | 美女啪啪无遮挡 | 奇米成人网| 国产又粗又猛 | 高潮毛片7777777毛片 | 中国黄色免费 | 国产在线资源 | 欧美freesex黑人又粗又大 | 久草成人| 99久久久久久久 | 91极品国产 | 黑人性xxx|