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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++ 结构体内存对齐

發(fā)布時(shí)間:2023/12/20 c/c++ 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 结构体内存对齐 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

剛出學(xué)校那會(huì),出去找實(shí)習(xí)工作,面試答題被問(wèn)到結(jié)構(gòu)體內(nèi)存大小的問(wèn)題,雖然自己以前接觸過(guò),但是也還是答錯(cuò)了,最終面試的這份工作黃了。一年后的最近,還是在找工作的路上,面試了一家游戲公司,其中也是答題環(huán)節(jié)有一道題被問(wèn)到結(jié)構(gòu)體的內(nèi)存大小,也還是答錯(cuò)了,最后面試也還是黃了。

到了現(xiàn)在自己才醒悟過(guò)來(lái),這些知識(shí)點(diǎn)是有多么的重要,所以咬緊牙,把這個(gè)內(nèi)容的知識(shí)點(diǎn)啃下來(lái),寫(xiě)下這篇博客記錄下來(lái)!


先看一段簡(jiǎn)單的程序

#include <iostream>using namespace std;typedef struct A {char c;int i; };typedef struct B {char c;int i;double d; };typedef struct C {char c;int i;double d;char c1; };int main(void) {cout << "struct A size = " << sizeof(struct A) << endl;cout << "struct B size = " << sizeof(struct B) << endl;cout << "struct C size = " << sizeof(struct C) << endl;return 0; }

如果不運(yùn)行,那么大家知道結(jié)構(gòu)體A、B、C所占用的內(nèi)存大小是多少嗎?

運(yùn)行截圖:

以上輸出的結(jié)果并非實(shí)際成員占用的字節(jié)數(shù),這就是結(jié)構(gòu)體的內(nèi)存對(duì)齊!

按照我們正常的邏輯,結(jié)構(gòu)體A的內(nèi)存大小應(yīng)該是5個(gè)字節(jié),結(jié)構(gòu)體B的內(nèi)存大小應(yīng)該是13個(gè)字節(jié),結(jié)構(gòu)體C的內(nèi)存大小應(yīng)該是14字節(jié)才對(duì)!
但是為什么是8、16和24呢?將在下面進(jìn)行講解。

結(jié)構(gòu)體內(nèi)存對(duì)齊原因

  • 平臺(tái)原因(移植原因):
    “不是所有的硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù);某些硬件平臺(tái)只能在某些特定地址處取某些特定的數(shù)據(jù),否則就會(huì)拋出硬件異常”。也就是說(shuō)在計(jì)算機(jī)在內(nèi)存讀取數(shù)據(jù)時(shí),只能在規(guī)定的地址處讀數(shù)據(jù),而不是內(nèi)存中任意地址都是可以讀取的。

  • 效率原因:
    正是由于只能在特定的地址處讀取數(shù)據(jù),所以在訪問(wèn)一些數(shù)據(jù)時(shí),對(duì)于訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要進(jìn)行兩次訪問(wèn);而對(duì)于對(duì)齊的內(nèi)存,只需要訪問(wèn)一次就可以。 其實(shí)這是一種以空間換時(shí)間的做法,但這種做法是值得的。

  • 結(jié)構(gòu)體對(duì)齊規(guī)則

  • 第一個(gè)成員在結(jié)構(gòu)體變量偏移量為0 的地址處,也就是第一個(gè)成員必須從頭開(kāi)始。

  • 其他成員變量要對(duì)齊到某個(gè)數(shù)字(對(duì)齊數(shù))的整數(shù)倍的地址處。對(duì)齊數(shù)為編譯器默認(rèn)的一個(gè) 對(duì)齊數(shù)與該成員大小中的較小值。vs中默認(rèn)值是8 Linux默認(rèn)值為4(可以通過(guò)#pragma pack (N) 修改,使用#pragma pack(show) 可以查看對(duì)齊值),但修改時(shí)N的取 值只能設(shè)置成1, 2,4,8,16.

  • 結(jié)構(gòu)體總大小為最大對(duì)齊數(shù)的整數(shù)倍。(每個(gè)成員變量都有自己的對(duì)齊數(shù))

  • 如果嵌套結(jié)構(gòu)體,嵌套的結(jié)構(gòu)體對(duì)齊到自己的最大對(duì)齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整體大小就是 所有最大對(duì)齊數(shù)(包含嵌套結(jié)構(gòu)體的對(duì)齊數(shù))的整數(shù)倍。(具體詳情,請(qǐng)看下面代碼結(jié)構(gòu)體G)

  • 結(jié)構(gòu)體對(duì)齊的規(guī)則都是依據(jù)上面四條規(guī)則進(jìn)行的!

    結(jié)構(gòu)體對(duì)齊示例

    typedef struct A {char c;int i; };

    根據(jù)第二和第三條規(guī)則,VS中最大默認(rèn)對(duì)齊數(shù)是8,結(jié)構(gòu)體中最小的是int類(lèi)型的4,8 < 4,所以結(jié)構(gòu)體A的對(duì)齊數(shù)是4.
    所以即使char類(lèi)型占一個(gè)字節(jié),但是他在內(nèi)存中也會(huì)占用4個(gè)字節(jié),來(lái)對(duì)齊4字節(jié)數(shù),這就是所謂的,犧牲空間來(lái)?yè)Q取時(shí)間!

    后面的也是一樣的道理!

    如果是這樣的結(jié)構(gòu)體,那么他們的內(nèi)存將會(huì)是多少呢?

    typedef struct D {char c;int i;double d;char c1;int b;char c2; };typedef struct E {int i;double d;char c;double d2; };typedef struct F {int i;double d;char c;double d2;int i2;int i3;char c2;char c3;char c4;int i4; };typedef struct G {int i;double d;struct E e;char c;double d2; };


    下面是他們的內(nèi)存關(guān)系圖:


    上述四張圖基本涵蓋了所有情況,希望這四張圖大家能看明白是怎么個(gè)回事!

    我本人的理解
    以它為例,

    typedef struct D {char c;int i;double d;char c1;int b;char c2; };

    首先我會(huì)先找到結(jié)構(gòu)體中最大的變量字節(jié)大小(內(nèi)部結(jié)構(gòu)體除外),然后使用加法原則向其對(duì)齊。(結(jié)構(gòu)體D的對(duì)齊數(shù)是8)
    c 是1個(gè)字節(jié),i是4個(gè)字節(jié),c + i 等于5字節(jié),為了符合內(nèi)存對(duì)齊的原則,他倆占用最前方8個(gè)字節(jié)的內(nèi)存,當(dāng)然c是占4個(gè)字節(jié),i也是占4個(gè)字節(jié),這樣4 + 4 等于8,才符合內(nèi)存對(duì)齊。
    d是8個(gè)字節(jié),緊接著后面存儲(chǔ)8個(gè)字節(jié)。
    c1是一個(gè)字節(jié),b是4個(gè)字節(jié),計(jì)算規(guī)格和上面一樣,占用8個(gè)字節(jié)。
    最后剩余一個(gè)c2是一個(gè)字節(jié),當(dāng)然為了符合內(nèi)存對(duì)齊的原則他在結(jié)構(gòu)體中是占8個(gè)字節(jié)的。
    所以最后計(jì)算出內(nèi)存大小為:
    (c + i) == 8(字節(jié))
    d == 8(字節(jié))
    (c1 + b) == 8(字節(jié))
    c2 == 8(字節(jié))
    8 + 8 + 8 + 8 == 32(字節(jié))

    相信再配合下圖,一定可以理解是什么原理的:


    總結(jié)
    結(jié)構(gòu)體內(nèi)存對(duì)齊這是比較底層的知識(shí)點(diǎn)了,當(dāng)然這也是我們程序員需要掌握的,特別是服務(wù)器開(kāi)發(fā)人員。
    對(duì)齊時(shí)需要注意對(duì)齊數(shù)!

    總結(jié)

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

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