欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言結(jié)構(gòu)體字節(jié)對齊的實現(xiàn)深入分析

 更新時間:2022年10月19日 15:06:27   作者:是星星鴨  
這篇文章主要介紹了C語言結(jié)構(gòu)體字節(jié)對齊的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

本教程可能會用到一點匯編的知識,看不懂沒關(guān)系,知道是那個意思就行了。使用的工具是vs2010。

一、什么是字節(jié)對齊

字節(jié)對齊是字節(jié)按照一定規(guī)則在空間上排列。

現(xiàn)代計算機中內(nèi)存空間都是按照byte劃分的,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定類型變量的時候經(jīng)常在特 定的內(nèi)存地址訪問,這就需要各種類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,而不是順序的一個接一個的排放,這就是對齊。

在我們之前寫程序的時候可能會發(fā)現(xiàn)有的時候你定義的變量是一個字節(jié),但是他在內(nèi)存中依然按照四個字節(jié)給你存儲,因為在32為系統(tǒng)中,4字節(jié)對齊執(zhí)行效率是最快的。這就是一種犧牲內(nèi)存換取性能的方案。

舉個栗子

我們知道,全局變量在在內(nèi)存中是有一個固定的地址的,如果不重新編譯的話,這個地址是不會改變的。所以我們拿全局變量舉例。

如下,我們定義兩個全局變量:

一個是char(單字節(jié))的一個是int(4字節(jié)的)

然后我們在main函數(shù)中給他們賦值,如下:

然后斷點、F7編譯、F5調(diào)試、ALT+8轉(zhuǎn)到反匯編:

可以看到他們之間差值為4字節(jié)

再次測試,如下:

反匯編:

差值為2。

因為字節(jié)對齊的原因,int類型的起始地址必須是4的整數(shù)倍,short類型的起始地址也必須是2的倍數(shù),當然char就沒有那么約束了,因為它只是一個字節(jié)的。并不是說char類型的變量與int變量的差值是因為int類型占了四個字節(jié)所以差值才為4 。

再做測試,如下:

打亂順序。查看反匯編:

總結(jié)如圖。

再次強掉、因為字節(jié)對齊的原因,變量的起始地址必須是變量字節(jié)大小的整數(shù)倍

二、結(jié)構(gòu)體字節(jié)對齊

結(jié)構(gòu)體中成員的存儲方式也是按照上面的字節(jié)對齊方式進行存儲的。不過有一點區(qū)別:結(jié)構(gòu)體的起始地址是其最寬數(shù)據(jù)類型的整數(shù)倍(千萬不要死記:結(jié)構(gòu)體寬度就是最寬數(shù)據(jù)類型的整數(shù)倍,因為這樣容易忘,下面我來和大家分析為什么是這樣,知道為什么才能記得更久)。

舉個栗子

結(jié)果:

我們分析一下:

int 4字節(jié)、char 1字節(jié)、double 8字節(jié),按理說應該是13字節(jié)對吧。

分析如下:

int類型占了4個字節(jié),這個時候char類型因為字節(jié)對齊的原因、他的起始地址是1的整數(shù)倍,所以它可以挨著int類型。但是double,他是8個字節(jié)的,由于字節(jié)對齊的原因、他的起始地址必須是8的倍數(shù),所以他和char類型之間會差3。但是int、char、double他們是一個結(jié)構(gòu)體的成員,不是分開存儲的。所以char和double之間空的三個字節(jié)因為字節(jié)對齊的原因必須補齊。

再來:

可以先猜測一下結(jié)果。

結(jié)果如下:

這里大家可以試著推測,只需要記住因為字節(jié)對齊的原因,char起始地址必須是1的整數(shù)倍、int必須是4的整數(shù)倍等等。

三、#pragma pack()的使用

當對內(nèi)存要求較高的時候,我們不得不拋棄性能。這個時候可以通過#pragma pack(n)來強制結(jié)構(gòu)體成員的對齊方式

#pragma pack(1)

struct st_info

{

char a;

int b;

};

#pragma pack()

<1> #pragma pack(n)中的n用來設定變量以n字節(jié)的方式對齊,可以設定的值包括:1、2、4、8,VC編譯器默認是8。

<2> 若需要強制取消字節(jié)對齊方式,則可使用#pragma pak()取消。

舉個栗子:

示例代碼:

#include <stdio.h>
#include <Windows.h>
#pragma pack(2)
struct stinfo
{
	char   t;
	int    x;
	char   y;
	double m;
};
#pragma pack()
int main()
{
	printf("%d\n", sizeof(stinfo));
 
	while(1);
	return 0;
}

如下:

這里我們讓結(jié)構(gòu)體以2字節(jié)的方式對齊,所以猜想:

char t因為字節(jié)對齊的原因起始地址應該是2的整數(shù)倍,但是他是首地址,不用管。

t = 1個字節(jié)。

int x類型因為pack(2)的原因,起始地址應該是2的整數(shù)倍,所以它和chart的差值應該為2,也就是補1個字節(jié)。

t+1+x = 6個字節(jié)

到這里,t和x已經(jīng)占有6個字節(jié)。

char y因為pack(2)的原因,他的起始地址應該是2的整數(shù)倍,但是上面六個字節(jié)正好是2的倍數(shù)。

t+1+x+y = 7個字節(jié)

到這里t、x、y三個成員已經(jīng)占有7個字節(jié)。

double m因為pack(2)的原因,起始地址不得不是2的整數(shù)倍,但是上面7個字節(jié)顯然不對,所以因為字節(jié)對齊的原因,上面t、x、y三個成員需要再補一個字節(jié),這個時候加上double的8個字節(jié)。

t+1+x+y+1+8 = 16個字節(jié)

結(jié)果如下:

猜想正確。

如果我們不強制字節(jié)對齊的話:

char t一個字節(jié)

int x起始地址必須是4的整數(shù)倍,所以t必須補3個字節(jié)

x+t+3 = 8個字節(jié)

char y一個字節(jié)

x+t+3+y = 9個字節(jié)

double m起始地址必須是8的倍數(shù),所以x+t+y需要補7個字節(jié)。

x+t+3+y+7+8 = 24個字節(jié)

結(jié)果如下:

對于pack(1)、pack(4)、pack(8)大家自己嘗試下吧。

總結(jié)

通過上面的講解,想必大家應該知道結(jié)構(gòu)體的字節(jié)數(shù)為什么是成員中最寬數(shù)據(jù)類型字節(jié)數(shù)的整數(shù)倍了的,但是還是那句話,不要死記這一點,明白為什么才是重點、才能記得更久。

因為字節(jié)對齊的原因、結(jié)構(gòu)體中成員的起始地址、假設該成員是int類型,那么它的起始地址必須是4的整數(shù)倍,如果是double類型,那么他的起始地址必須是8的整數(shù)倍。當然也可以強制他們的起始地址是一個固定數(shù)字(1、2、4、8)的整數(shù)倍。通過#pragma pack(n)即可。

到此這篇關(guān)于C語言結(jié)構(gòu)體字節(jié)對齊的實現(xiàn)深入分析的文章就介紹到這了,更多相關(guān)C語言結(jié)構(gòu)體字節(jié)對齊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++賦值函數(shù)+移動賦值函數(shù)+移動構(gòu)造函數(shù)詳解

    C++賦值函數(shù)+移動賦值函數(shù)+移動構(gòu)造函數(shù)詳解

    這篇文章主要介紹了C++賦值函數(shù)+移動賦值函數(shù)+移動構(gòu)造函數(shù)詳解,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • C++線程之thread詳解

    C++線程之thread詳解

    這篇文章主要為大家詳細介紹了C++線程中的thread,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • C++類和對象深入探索之分文件編寫點和圓的關(guān)系詳解

    C++類和對象深入探索之分文件編寫點和圓的關(guān)系詳解

    先前把C++類和對象的封裝講完了,并且留下了一個判斷兩個立方體是否相等的案例,但是那么多知識點,僅僅一個案例是不夠的,所以再來一個分文件編寫點圓關(guān)系的案例;創(chuàng)建圓類和點類,圓類包含點類,算是一個嵌套吧,順便復習一下分文件編寫的方法,開整
    2022-05-05
  • C語言實現(xiàn)學生信息管理系統(tǒng)(多文件)

    C語言實現(xiàn)學生信息管理系統(tǒng)(多文件)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)學生信息管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • C++中的模板類&模板函數(shù)

    C++中的模板類&模板函數(shù)

    這篇文章主要介紹了C++中的模板類&模板函數(shù)用法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • C++實現(xiàn)四則混合運算計算器

    C++實現(xiàn)四則混合運算計算器

    這篇文章主要為大家詳細介紹了C++實現(xiàn)四則混合運算計算器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • C語言數(shù)據(jù)結(jié)構(gòu)之單鏈表的實現(xiàn)

    C語言數(shù)據(jù)結(jié)構(gòu)之單鏈表的實現(xiàn)

    鏈表是一種物理存儲結(jié)構(gòu)上非連續(xù)、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的。本文將用C語言實現(xiàn)單鏈表,需要的可以參考一下
    2022-06-06
  • C++各種輸出數(shù)據(jù)類型詳解

    C++各種輸出數(shù)據(jù)類型詳解

    這篇文章主要介紹了C++各種輸出數(shù)據(jù)類型,在C++中,可以使用cout對象和插入運算符<<輸出各種數(shù)據(jù)類型,包括整數(shù)類型、浮點數(shù)類型、字符類型、字符串類型和布爾類型,需要的朋友可以參考下
    2023-06-06
  • Qt如何實現(xiàn)輸入框@聯(lián)系人的@檢測的示例

    Qt如何實現(xiàn)輸入框@聯(lián)系人的@檢測的示例

    本文主要介紹了Qt如何實現(xiàn)輸入框@聯(lián)系人的@檢測的示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • c++連續(xù)輸入未知個數(shù)的數(shù)字操作

    c++連續(xù)輸入未知個數(shù)的數(shù)字操作

    這篇文章主要介紹了c++連續(xù)輸入未知個數(shù)的數(shù)字操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12

最新評論