<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > MDK對齊方式設定

MDK對齊方式設定

作者: 時(shí)間:2016-11-27 來(lái)源:網(wǎng)絡(luò ) 收藏
__align(4) u8 mem1base[MEM1_MAX_SIZE];

為何要字節對齊?

本文引用地址:http://dyxdggzs.com/article/201611/322520.htm

從理論上講似乎對任何類(lèi)型的變量的訪(fǎng)問(wèn)可以從任何地址開(kāi)始,但實(shí)際情況是在訪(fǎng)問(wèn)特定類(lèi)型變量的時(shí)候經(jīng)常在特定的內存地址訪(fǎng)問(wèn),各個(gè)硬件平臺對存儲空間的處理上有很大的不同。一些平臺對某些特定類(lèi)型的數據只能從某些特定地址開(kāi)始存取。

MDK 字節對齊關(guān)鍵字 __packed

typedef __packed struct abc
{
int a;
int b;
}strabc;

vxworks 字節對齊關(guān)鍵字 _WRS_PACK_ALIGN(1)

typedefstruct abc
{
int a;
int b;
}_WRS_PACK_ALIGN(1) strabc;

(1)什么是字節對齊
一個(gè)變量占用 n 個(gè)字節,則該變量的起始地址必須能夠被 n 整除,即: 存放起始地址 % n = 0, 對于結構體而言,這個(gè) n 取其成員種的數據類(lèi)型占空間的值最大的那個(gè)。
(2)為什么要字節對齊
內存空間是按照字節來(lái)劃分的,從理論上說(shuō)對內存空間的訪(fǎng)問(wèn)可以從任何地址開(kāi)始,但是在實(shí)際上不同架構的CPU為了提高訪(fǎng)問(wèn)內存的速度,就規定了對于某些類(lèi) 型的數據只能從特定的起始位置開(kāi)始訪(fǎng)問(wèn)。這樣就決定了各種數據類(lèi)型只能按照相應的規則在內存空間中存放,而不能一個(gè)接一個(gè)的順序排列。

舉個(gè)例子,比如有些平臺訪(fǎng)問(wèn)內存地址都從偶數地址開(kāi)始,對于一個(gè)int型(假設32位系統),如果從偶數地址開(kāi)始的地方存放,這樣一個(gè)讀周期就可以讀出這 個(gè)int數據,但是如果從奇數地址開(kāi)始的地址存放,就需要兩個(gè)讀周期,并對兩次讀出的結果的高低字節進(jìn)行拼湊才能得到這個(gè)int數據,這樣明顯降低了讀取 的效率。
(3)如何進(jìn)行字節對齊

每個(gè)成員按其類(lèi)型的對齊參數(通常是這個(gè)類(lèi)型的大小)和指定對齊參數(不指定則取默認值)中較小的一個(gè)對齊,并且結構的長(cháng)度必須為所用過(guò)的所有對齊參數的整數倍,不夠就補空字節。

這個(gè)規則有點(diǎn)苦澀,可以把這個(gè)規則分解一下,前半句的意思先獲得對齊值后與指定對齊值進(jìn)行比較,其中對齊值獲得方式如下:

1. 數據類(lèi)型的自身對齊值為:對于char型數據,其自身對齊值為1,對于short型為2,對于int, long, float類(lèi)型,其自身對齊值為4,對于 double 類(lèi)型其自身對齊值為8,單位為字節。
2.結構體自身對齊值:其成員中自身對齊值最大的那個(gè)值。

其中指定對齊值獲得方式如下:

#pragma pack (value)時(shí)的指定對齊值value。

未指定則取默認值。

后半句的意思是主要是針對于結構體的長(cháng)度而言,因為針對數據類(lèi)型的成員,它僅有一個(gè)對齊參數,其本身的長(cháng)度、于這個(gè)對齊參數,即1倍。對于結構體而言,它 可能使用了多種數據類(lèi)型,那么這句話(huà)翻譯成對齊規則: 每個(gè)成員的起始地址 % 自身對齊值 = 0,如果不等于 0 則先補空字節直至這個(gè)表達式成立。
換句話(huà)說(shuō),對于結構體而言,結構體在在內存的存放順序用如下規則即可映射出來(lái):
(一)每個(gè)成員的起始地址 % 每個(gè)成員的自身對齊值 = 0,如果不等于 0 則先補空字節直至這個(gè)表達式成立;
(二)結構體的長(cháng)度必須為結構體的自身對齊值的整數倍,不夠就補空字節。

舉個(gè)例子:

#pragma pack(8)
struct A{
char a;
long b;
};

struct B{
char a;
struct A b;
long c;
};

struct C{
char a;
struct A b;
double c;
};

struct D{
char a;
struct A b;
double c;
int d;
};

struct E{
char a;
int b;
struct A c;
double d;
};


對于 struct A 來(lái)說(shuō),對于char型數據,其自身對齊值為1,對于long類(lèi)型,其自身對齊值為4, 結構體的自身對齊值取其成員最大的對齊值,即大小4。那么struct A 在內存中的順序步驟為:
(1) char a, 地址范圍為0x0000~0x0000,起始地址為0x0000,滿(mǎn)足 0x0000 % 1 = 0,這個(gè)成員字節對齊了。
(2) long b, 地址起始位置不能從0x00001開(kāi)始,因為 0x0001 % 4 != 0,所以先補空字節,直到0x00003結束,即補3個(gè)字節的空字節,從0x00004開(kāi)始存放b,其地址范圍為0x00004~0x0007.
(3)此時(shí)成員都存放結束,結構體長(cháng)度為8,為結構體自身對齊值的2倍,符合條件(二).
此時(shí)滿(mǎn)足條件(一)和條件(二),struct A 中各成員在內存中的位置為:a*** b ,sizeof(struct A) = 8。(每個(gè)星號代表一位,成員各自代表自己所占的位,比如a占一位,b占四位)

對于struct B,里面有個(gè)類(lèi)型為struct A的成員b自身對齊值為4,對于long類(lèi)型,其自身對齊值為4. 故struct B的自身對齊值為4。那么struct B 在內存中的順序步驟為:
(1) char a, 地址范圍為0x0000~0x0000,起始地址為0x0000,滿(mǎn)足 0x0000 % 1 = 0,這個(gè)成員字節對齊了。
(2) struct A b, 地址起始位置不能從0x00001開(kāi)始,因為 0x0001 % 4 != 0,所以先補空字節,直到0x00003結束,即補3個(gè)字節的空字節,從0x00004開(kāi)始存放b,其地址范圍為0x00004~0x00011.
(3) long c,地址起始位置從0x000012開(kāi)始, 因為 0x0012 % 4 = 0,其地址范圍為0x00012~0x0015.
(4)此時(shí)成員都存放結束,結構體長(cháng)度為16,為結構體自身對齊值的4倍,符合條件(二).
此時(shí)滿(mǎn)足條件(一)和條件(二),struct B 中各成員在內存中的位置為:a*** b c ,sizeof(struct C) = 24。(每個(gè)星號代表一位,成員各自代表自己所占的位,比如a占一位,b占八位,c占四位)
對于struct C,里面有個(gè)類(lèi)型為struct A的成員b自身對齊值為4,對于double 類(lèi)型,其自身對齊值為8. 故struct C的自身對齊值為8。那么struct C 在內存中的順序步驟為:
(1) char a, 地址范圍為0x0000~0x0000,起始地址為0x0000,滿(mǎn)足 0x0000 % 1 = 0,這個(gè)成員字節對齊了。
(2) struct A b, 地址起始位置不能從0x00001開(kāi)始,因為 0x0001 % 4 != 0,所以先補空字節,直到0x00003結束,即補3個(gè)字節的空字節,從0x00004開(kāi)始存放b,其地址范圍為0x00004~0x00011.
(3) double c,地址起始位置不能從0x000012開(kāi)始, 因為 0x0012 % 8 != 0,所以先補空字節,直到0x000015結束,即補4個(gè)字節的空字節,從0x00016開(kāi)始存放c,其地址范圍為0x00016~0x0023.
(4)此時(shí)成員都存放結束,結構體長(cháng)度為24,為結構體自身對齊值的3倍,符合條件(二).
此時(shí)滿(mǎn)足條件(一)和條件(二),struct C 中各成員在內存中的位置為:a*** b **** c ,sizeof(struct C) = 24。(每個(gè)星號代表一位,成員各自代表自己所占的位,比如a占一位,b占八位,c占八位)

對于struct D,自身對齊值為8。前面三個(gè)成員與 struct C 是一致的。對于第四成員d,因為 0x0024 % 4 = 0, 所以可以從0x0024開(kāi)始存放d, 其地址范圍為0x00024~0x00027.此時(shí)成員都存放結束,結構體長(cháng)度為28,28 不是結構體自身對齊值8的倍數,所以要在后面補四個(gè)空格,即在0x0028~0x0031上補四個(gè)空格。補完了,結構體長(cháng)度為32, 為結構體自

身對齊值的4被,,符合條件(二).
此時(shí)滿(mǎn)足條件(一)和條件(二),struct D 中各成員在內存中的位置為:a*** b **** c d **** ,sizeof(struct D) = 32。(每個(gè)星號代表一位,成員各自代表自己所占的位,比如a占一位,b占八位,c占八位, d占四位)。

對于struct E 中各成員在內存中的位置為:a*** b c d, sizeof(struct E) = 24。(每個(gè)星號代表一位,成員各自代表自己所占的位,比如a占一位,b占四位,c占八位, d占八位)。
通過(guò)struct D 和 struct E 可以看出,在成員數量和類(lèi)型一致的情況,后者的所占空間少于前者,因為后者的填充空字節要少。如果我們在編程時(shí)考慮節約空間的話(huà),應該遵循將變量按照類(lèi)型 大小從小到大聲明的原則, 這樣盡量減少填補空間。另外,可以在填充空字節的地方來(lái)插入reserved成員, 例如
struct A
{
char a;
char reserved[3];
int b;
};
這樣做的目的主要是為了對程序員起一個(gè)提示作用,如果不加則編譯器會(huì )自動(dòng)補齊。

習題

typedef struct

{

int a;//ARM(int=4)51(int=2)

char b;// 1

short c;// 2

}AAA;

typedef struct

{

char b;

int a;

short c;

}BBB;

i = sizeof(AAA);

j = sizeof(BBB);

//注意在51單片機,ARM,PC不同

51 (i=j=5)//好像強制單字節對齊

ARM(i=8,j=12)//按規則默認對齊

PC(i=8,j=12)

AAA對齊方式如下(ARM)

I I I I

I0I I

BBB對齊方式如下(ARM)

I0 0 0

IIII

I I0 0

通過(guò)#pragma pack可以調整對齊字節數

#pragma pack(1) //指定Align為 1字節;

。。。。。。。。。。。。//需要對齊的結構體

#pragma pack() //恢復到原先值



關(guān)鍵詞: MDK對齊方

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>