欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
C語(yǔ)言中的字節對齊

一、什么是字節對齊
一個(gè)基本類(lèi)型的變量在內存中占用n個(gè)字節,則該變量的起始地址必須能夠被n整除,即: 存放起始地址 % n = 0,那么,就成該變量是字節對齊的;對于結構體、聯(lián)合體而言,這個(gè)n取其所有基本類(lèi)型的成員中占用空間字節數最大的那個(gè);
內存空間是以字節為基本單位進(jìn)行劃分的,從理論上講,似乎對任何類(lèi)型的變量的訪(fǎng)問(wèn)都可以從任何地址處開(kāi)始,但實(shí)際情況是在訪(fǎng)問(wèn)特定類(lèi)型變量的時(shí)候經(jīng)常是從特定的內存地址處開(kāi)始訪(fǎng)問(wèn),這就需要各種類(lèi)型的數據只能按照一定的規則在空間上排列,而不是順序的一個(gè)接一個(gè)地排放;究其原因,是為了使不同架構的CPU可以提高訪(fǎng)問(wèn)內存的速度,就規定了對于特定類(lèi)型的數據只能從特定的內存位置處開(kāi)始訪(fǎng)問(wèn);所以,各種類(lèi)型的數據只能按照相應的規則在內存空間上排放,而不能順序地、連續地、一個(gè)一個(gè)地排放;這就是內存對齊;
二、為什么需要字節對齊
由于各種硬件平臺對存儲空間的處理上有很大的不同;一些平臺對某些特定類(lèi)型的數據只能從某個(gè)特定內存地址處開(kāi)始訪(fǎng)問(wèn);比如:有些架構的CPU在訪(fǎng)問(wèn)一個(gè)沒(méi)有進(jìn)行對齊的變量的時(shí)候會(huì )發(fā)生錯誤,那么在這種架構下編程時(shí)就必須保證字節對齊;其它平臺可能沒(méi)有這種情況,但最常見(jiàn)的是,如果不按照適合其平臺要求對數據進(jìn)行對齊,會(huì )在存取效率上帶來(lái)?yè)p失;比如,有些平臺每次讀取數據都是從偶地址處開(kāi)始,如果一個(gè)int(假設為32位系統)型數據從偶地址處開(kāi)始存放,那么只需要一個(gè)讀指令周期就可以完全讀出這個(gè)32bit的int型數據,相反,如果這個(gè)32bit的int型數據是從奇地址處開(kāi)始存放,那么就需要兩個(gè)讀指令周期才能完全讀出這個(gè)32bit的int數據,并且還需要對這兩次讀出的結果的高低字節進(jìn)行重新拼湊才能得到正確的32bit數據;這個(gè)時(shí)候,CPU的讀取效率明顯下降;
三、字節對齊規則
預處理指令#pragma pack(align_value)用于指定對齊值,而預處理指令#pragma pack()用于取消上次設定的對齊值,恢復默認對齊值;
字節對齊是針對基本類(lèi)型變量的;基本類(lèi)型變量有:char、unsigned char、short、unsigned short、int、unsigned int、long、unsigned long、long long、unsigned long long、float、double,等等;所以,對于結構體的對齊也只能按照其成員變量中的基本類(lèi)型來(lái)對齊了;
有四個(gè)概念需要理解:
A、數據類(lèi)型自身的對齊值:
   是指對該數據類(lèi)型使用sizeof()操作符進(jìn)行操作所得到的大小(單位,字節);比如,對于[unsigned] char類(lèi)型的數據,其自身對齊值為1字節;對于[unsigned] short類(lèi)型的數據,其自身對齊值是2字節;對于[unsigned] int、[unsigned] long、[unsigned] long long、float、double等數據類(lèi)型,其自身對齊值是4字節;
B、結構體、聯(lián)合體、類(lèi)的自身對齊值:
   是指其所有基本類(lèi)型的成員中,自身對齊值最大的那個(gè)值;如果這些復合類(lèi)型中有嵌套類(lèi)型或復合類(lèi)型的變量,則需要把這些嵌套的類(lèi)型或復合類(lèi)型的變量拆解成基本類(lèi)型的成員之后再對齊;
C、指定對齊值:
   是指使用預處理指令#pragma pack(align_value)指定的對齊值align_value;
D、數據成員、結構體和類(lèi)的有效對齊值:
   是指其自身對齊值和指定對齊值中較小的那個(gè)值;
其中,有效對齊值是最終用來(lái)決定數據存放地址方式的值,最重要;設定有效對齊值為N,就表示"對齊在N字節上",也就是說(shuō),該數據的"存放起始地址%N=0";

因此,每個(gè)類(lèi)型的數據的有效對齊值就是其自身對齊值(通常是這個(gè)類(lèi)型的大小)和指定對齊值(不指定則取默認值)中較小的那個(gè)值,并且結構體自身對齊值是其所有成員中自身對齊值最大的那個(gè)值;

字節對齊的細節與編譯器的實(shí)現有關(guān),但一般來(lái)說(shuō),結構體需要滿(mǎn)足以下幾個(gè)準則:
1).從結構體外部來(lái)看,結構體變量的首地址能夠被其最寬基本成員的大小整除;從結構體內部來(lái)看,它的第一個(gè)數據成員的地址相對于整個(gè)結構體首地址的偏移量為0,也就是說(shuō),結構體的第一個(gè)數據成員存放在偏移量為0的地方;
2).結構體中的每個(gè)數據成員的有效對齊值都取其自身對齊值和指定對齊值中的較小的那個(gè)對齊值;或者說(shuō)是,結構體中的每個(gè)數據成員相對于結構體首地址的偏移量都是該數據成員大小和指定對齊值中較小的那個(gè)值(或有效對齊值)的整數倍,如有需要,編譯器會(huì )在數據成員之間加上填充字節;
3).如果結構體中還有嵌套的結構體或結構體變量,那么就要把這些嵌套進(jìn)去的結構體或結構體變量拆成基本類(lèi)型成員,并取其最長(cháng)的基本類(lèi)型成員的對齊方式;
4).結構體整體的有效對齊值必須為其最寬基本類(lèi)型成員大小的整數倍;或者說(shuō)是,結構體整體的大小為結構體中最寬基本類(lèi)型成員大小的整數倍,如有需要,編譯器會(huì )在最末一個(gè)成員之后加上填充字節;換句話(huà)說(shuō)是,結構體整體的有效對齊值按照結構體中最寬基本類(lèi)型成員的大小和指定對齊值中較小的那個(gè)值進(jìn)行;
注意:如果指定對齊值大于自身對齊值,則指定對齊值無(wú)效;

例1:不帶嵌套的
#pragma pack(4) //指定按照4字節對齊
struct TestA
{
  int   a;  //第一個(gè)成員,自身長(cháng)4,#pragma pack(4),取較小值,按照4字節對齊,放在[0,3]偏移的位置;
  char  b;  //第二個(gè)成員,自身長(cháng)1,#pragma pack(4),取較小值,按照1字節對齊,放在[4]偏移的位置;
  short c;  //第三個(gè)成員,自身長(cháng)1,#pragma pack(4),取較小值,按照2字節對齊,偏移量必須是2的整數倍,故,存放在[6,7]偏移的位置;
  char  d;  //第四個(gè)成員,自身長(cháng)1,#pragma pack(4),取較小值,按照1字節對齊,放在[8]偏移的位置;
};
#pragma pack() //取消4字節對齊,恢復默認對齊值;
因此,整個(gè)結構體占用的有效字節為9個(gè)字節;由于結構體整體的對齊值和大小是其最寬基本類(lèi)型成員大小的整數倍,即:按照最寬基本類(lèi)型成員大小和指定對齊值中較小的值對齊的;因為結構體最寬基本類(lèi)型成員的大小是4字節,其有效對齊值也是4字節,而9字節按照4字節圓整的結果是12字節,所以,sizeof(TestA)=12;
#pragma pack(2) //指定按照2字節對齊
struct TestA
{
  int   a;  //第一個(gè)成員,自身長(cháng)4,#pragma pack(4),取較小值,按照2字節對齊,放在[0,3]偏移的位置;
  char  b;  //第二個(gè)成員,自身長(cháng)1,#pragma pack(2),取較小值,按照1字節對齊,放在[4]偏移的位置;
  short c;  //第三個(gè)成員,自身長(cháng)1,#pragma pack(2),取較小值,按照2字節對齊,偏移量必須是2的整數倍,故,存放在[6,7]偏移的位置;
  char  d;  //第四個(gè)成員,自身長(cháng)1,#pragma pack(2),取較小值,按照1字節對齊,放在[8]偏移的位置;
};
#pragma pack() //取消4字節對齊,恢復默認對齊值;
可以看出,只是改變了一下結構體之間的對齊方式,從4字節對齊改為2字節對齊;結果就不一樣了;
整個(gè)結構體所占用的有效字節數仍然是9字節,但是結構體整體的大小就變了,按照最寬基本類(lèi)型成員大小和指定對齊值中較小的值對齊;結構體中最寬基本類(lèi)型成員的大小事4字節,而指定對齊值是2字節對齊,取最小值2,所以,最后,整個(gè)結構體的大小就是9字節按照2字節圓整(取2的整數倍),于是,sizeof(TestA)=10;
例2:帶嵌套的
#pragma pack(2)
struct A
{
  char c;   //第一個(gè)成員,自身長(cháng)1,#pragma pack(2),取較小值,按照1字節對齊,放在[0]偏移的位置;
  int  i;   //第二個(gè)成員,自身長(cháng)4,#pragma pack(2),取較小值,按照2字節對齊,放在[2,5]偏移的位置;
};
struct B
{
  char c1;  //第一個(gè)成員,自身長(cháng)1,#pragma pack(2),取較小值,按照1字節對齊,放在[0]偏移的位置;
  A    s;   //第二個(gè)成員,自身長(cháng)6,#pragma pack(2),取較小值,按照2字節對齊,放在[2,7]偏移的位置;
  char c2;  //第三個(gè)成員,自身長(cháng)1,#pragma pack(2),取較小值,按照1字節對齊,存放在[8]偏移的位置;
};
#pragma pack()
結構體A占用的有效字節數是6字節;結構體A整體的大小要取其最寬基本類(lèi)型成員大小和指定對齊值中較小的那個(gè)值的整數倍,最寬基本類(lèi)型成員大小為4字節,指定對齊值為2字節,所以,6取較小的值2字節的整數倍為6字節;最終,結構體A的大小為:sizeof(A)=6;
結構體B占用的有效字節數是9字節;結構體B整體的大小要取其最寬基本類(lèi)型成員大小和指定對齊值中較小的那個(gè)值的整數倍,最寬基本類(lèi)型成員大小為6字節,指定對齊值為2字節,所以,9取較小的值2字節的整數倍為10字節;最終,結構體B的大小為:sizeof(B)=10;
四、總結
設置對齊方式有兩種方法;
第一種方法:
#pragma pack(n),指定按照n字節對齊;
#pragma pack(),取消自定義的對齊值;
第二種方法:
__attribute__((aligned(n))):讓所作用的結構體成員對齊在n字節自然邊界上;如果結構體中有成員的長(cháng)度大于n,則按照最大成員的長(cháng)度來(lái)對齊;即:按照機器能允許該類(lèi)的的最大長(cháng)度來(lái)對齊;這個(gè)恰好與#pragma pack(n)指令的相反;
__attribute__((packed)):取消結構體在編譯過(guò)程中的優(yōu)化對齊,按照實(shí)際占用字節數進(jìn)行對齊,等價(jià)于指令#pragma pack(1),即,按照1字節對齊;
其中,n=1,2,4,8,16,......等;
第一種方法比較常見(jiàn);

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
C語(yǔ)言結構體及其內存布局
關(guān)于內存對齊
細說(shuō)結構字節對齊
C語(yǔ)言結構體對齊問(wèn)題
簡(jiǎn)要講述C/C++中的操作符sizeof()
關(guān)于結構體的內存對齊
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久