溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

結構體大小的計算以及內(nèi)存對其原則和修改默認對齊數(shù)

發(fā)布時間:2020-08-11 20:28:59 來源:網(wǎng)絡 閱讀:350 作者:勿忘勛心 欄目:編程語言

1.結構體大小的計算

          **我們都知道,不論是數(shù)組還是指針都可以計算其大小,
             而同樣結構體也是可以計算大小的,
             接下來我們就深入討論如何計算結構體的大小。**

#include<stdio.h>
#includ<stdlib.h>
struct s1
{
    char c1;
    int a;
    char c2;

};

int main()
{
    printf("%d\n", sizeof(struct s1));
    system("pause");
    return 0;
}

大家猜猜這個求出來的結果多大呢,

話不多說,直接上結果圖;
結構體大小的計算以及內(nèi)存對其原則和修改默認對齊數(shù)

是不是很疑惑呢,下面我就講一講結構體的大小怎么計算。
在這之前,我們先了解一個概念

2.結構體的內(nèi)存對齊

首先內(nèi)存對齊有以下幾條規(guī)則

1.第一個成員在與結構體變量偏移量為0的地址處 (其實說白了就是和第一個成員變量的地址一樣,就是從第一個成員變量的地址開始計算);
2.其他成員變量要對齊到某個數(shù)字(對齊數(shù))的整數(shù)倍的地址處;
對齊數(shù)=min{編譯器默認的一個數(shù),該成員的大小};
一般呢,vs中默認值=8,linux中默認值=4;
3.結構體總大小就為最大對齊數(shù)的整數(shù)倍,
??!每一個成員變量都有一個對齊數(shù)??!
4.如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數(shù)的整數(shù)倍處,結構體的整體大小就是所有對齊數(shù)(含嵌套結構體的對齊數(shù))的整數(shù)倍。

下面我就分析一些具體的實例來幫大家理解;

#include<stdio.h>
#includ<stdlib.h>
struct s1
{
    char c1;     //min{1,8}=1
    int a;          //min{4,8}=4
    char c2;     //min{1,8}=1

};

int main()
{
    printf("%d\n", sizeof(struct s1));
    system("pause");
    return 0;
}

在剛剛這個例子中 他們的對齊數(shù)分別是1,4,1
首先在內(nèi)存中找一個位置放入第一個成員變量,也就是c1;=>對應規(guī)則1
然后下一個成員變量的對齊數(shù)為4,所以存放這個成員變量的時候他的首地址應該放在4的整數(shù)倍處;=>對應規(guī)則2
然后最后一個是c2,他的對齊數(shù)是1,就緊接著放,可能有的同學覺得到這就結束了,但其實并不是,c2放完了以后,后邊的三個字節(jié)也需要算上,而這么做的原因就要追溯到
=>規(guī)則3
所以最后就是12個字節(jié)的大小啦。
詳情圖解如下:
結構體大小的計算以及內(nèi)存對其原則和修改默認對齊數(shù)

看了上面的例子我想著大家可能已經(jīng)了解如何計算結構體的大小,
那么大家看一看下面的這個例子,

#include<stdio.h>
#includ<stdlib.h>
struct s2
{
    char q1;
    char q2;
    int i;

};

int main()
{
    printf("%d\n", sizeof(struct s2));
    system("pause");
    return 0;
}

結構體大小的計算以及內(nèi)存對其原則和修改默認對齊數(shù)

不知道大家有沒有發(fā)現(xiàn)這個例子和第一個例子是其實結構體成員都是一樣的,只是順序不一樣,我還是用圖來給大家講解一下。
結構體大小的計算以及內(nèi)存對其原則和修改默認對齊數(shù)

這里先放q1,占用一個字節(jié),然后q2的對齊數(shù)也是1,則緊接著放,占用一個字節(jié),i的對齊數(shù)為4,則i的首地址要放在4的倍數(shù)處,則從偏移量為4處開始放起,放完后一共8個字節(jié),同樣也是最大對齊數(shù)(4)的倍數(shù),就是這個結構體的大小。

通過這兩個例子,我們就需要想一想,在設計結構體時,怎樣才能滿足既要內(nèi)存對齊,又要節(jié)省空間呢,那就是 !!盡可能讓占用空間小的成員集中在一起。

看完這兩個例子,我想大家都已經(jīng)理解并且學會結構體大小的計算了吧,那么下面我們算一個結構體嵌套的大小。

#include<stdio.h>
#includ<stdlib.h>
struct  s3
{
    double a;
    char b;
    int c;
};

struct s4
{
    char d;
    struct s3 e;
    double f;
};

int main()
{
    printf("%d\n", sizeof(struct s3));
    printf("%d\n", sizeof(struct s4));
    system("pause");
    return 0;
}

結構體大小的計算以及內(nèi)存對其原則和修改默認對齊數(shù)

大家會不會算呢,
在有結構體嵌套問題的時候,記得嵌套的結構體對齊到自己的最大對齊數(shù)的整數(shù)倍處哦,而結構體的整體大小就是所有最大對齊數(shù)(含嵌套結構體的對齊數(shù))的整數(shù)倍。

那到這可能有的人要好奇為什么要存在內(nèi)存對齊呢,其原因有兩點:
1.平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。
2.性能原因:數(shù)據(jù)結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內(nèi)存,處理器需要做兩次內(nèi)存訪問;而對齊的內(nèi)存訪問僅需要一次訪問。

其實說白了就是用空間來換取時間是的做法

3.修改默認對齊數(shù)

最后我們再講一個知識點,就是修改默認的對齊數(shù);用的是#pragma這個預處理指令;

#include<stdio.h>
#includ<stdlib.h>
#pragma pack(1)  //設置默認對齊數(shù)為6
struct s5
{
    char a1;
    int i1;
    char a2;

};
#pragma pack()//取消設置的默認對齊數(shù),還原為vs自己默認的對齊數(shù)值
int main()
{
    printf("%d\n", sizeof(struct s5));
    system("pause");
    return 0;
}

結構體大小的計算以及內(nèi)存對其原則和修改默認對齊數(shù)

這個計算方法和上面的一模一樣,就是默認對齊數(shù)改變了而已。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI