c 結構體內存對齊詳解


0x00簡介

首先要知道結構體的對齊規制

1.第一個成員在結構體變量偏移量為0的地址處

2.其他成員變量對齊到某個數字的整數倍的地址處

對齊數=編輯器默認的一個對齊數與該成員大小的較小值

vs中默認的值為8

gcc 沒有默認就是累加

3.結構體總大小為最大對齊數(每個成員變量都有一個對齊數)的整數倍

4.如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整數體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍

0x01結構體

如下代碼

#include <string.h>
#include <stdio.h>

struct s1
{
    char c1;
    int a;
    char c2;

};

struct s2
{
    char c1;
    char c2;
    int a;

};


int  main()
{

    struct s1 s1 = { 0 };
    printf("%d", sizeof(s1));
    struct s2 s2 = { 0 };
    printf("%d", sizeof(s2));
    return 0;
}

s1 的偏移量大小計算就是:

從上到下

char c1;

他的字節是1  就是 1/8  取最小值 第一個就是1  此時偏移量大小就是1

int a;

他的字節是4  就是 4/8  取最小值 就是4  偏移量大小應該是4的倍數 前面1就要填充3個 就是 4 在加int  此時偏移量大小就是8

char c2;

他的字節是1  就是 1/8  取最小值 第一個就是1  由於他是最后一個完了就是結構體  此時偏移量是8+1=9 但是結構體總大小為最大對齊數(每個成員變量都有一個對齊數)的整數倍他個結構體最大對齊數是4 所以9不是4的倍數 要在填充3個  就是12個長度

s2的偏移量大小計算就是:

char c1;

他的字節是1  就是 1/8  取最小值 第一個就是1  此時偏移量大小就是1

char c2;

他的字節是1  就是 1/8  取最小值 第一個就是1 此時偏移量大小就是2

int a;

他的字節是4  就是 4/8  取最小值 就是4  偏移量大小應該是4的倍數 前面是2就要填充2個 就是 4 在加int  此時偏移量大小就是8 正好是4的倍數不用在加了

這時查看輸出結果

12
8

0x02結構體嵌套

這里我們在看一個結構體嵌套的代碼

#include <string.h>
#include <stdio.h>

struct s3
{
    double d;
    char  c;
    int i;

};

struct s4
{
    char c;
    struct s3 s3;
    double d;

};


int  main()
{
    printf("%d", sizeof(struct s4));
    return 0;
}

先計算s3結構體的大小

double d;

他的字節是8  就是 8/8  取最小值 第一個就是8  此時偏移量大小就是8

char  c;

他的字節是1  就是 1/8  取最小值 1  此時偏移量大小就是9

int i;

他的字節是4  就是 4/8  取最小值 4  前面偏移量是9 不是4的倍數要加3個 填充就是12 在加int   此時偏移量大小就是16 結構體最大對齊數是8所以要是8的倍數 正好是8的倍數不用加了

再來計算s4的結構體大小

char c;

他的字節是1  就是 1/8  取最小值 1  此時偏移量大小就是1

struct s3 s3;

他的字節是16  結構體的最大對齊數是8 只需要前面是8的倍數就行了  前面是1 要補齊7個  就是1+7+16=24

double d;

他是8個字節  就是8/8 取最小值8 前面偏移量是24  為8的倍數不用填充 直接+8 就是32  此時結構體結束 最大對齊數是8  32正好是8的倍數不用在填充

這個結構體就是32偏移量

0x03為什么要對齊?

1.平台原因:不是所有的硬件都可以在任意地址上讀數據。

2.性能原因:內存對齊就是拿空間換時間

0x04 修改默認對齊數

主要是使用#pragma這個預處理指令。 改名默認對齊數

#pragma pack(1)
struct s3
{
    double d;
    char  c;
    int i;

};
#pragma pack()

這里寫1 就是和gcc一樣的計算方式了 直接就是里面變量字節相加

這里是13

如果沒用到pragma 考慮到性能 結構體變量聲明應該是 字節小到大 例如:

struct s3
{
    char  c;
    char  c1;
    char  c2;
    int i;
    double d;
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM