www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > CPP開發(fā)者
[導(dǎo)讀]最近在做一個項(xiàng)目,遇到一個問題,運(yùn)行于ARM上的threadx在與DSP通信采用消息隊(duì)列的方式傳遞消息(最終實(shí)現(xiàn)原理是中斷共享內(nèi)存的方式),在實(shí)際操作過程中發(fā)現(xiàn)threadx總是crash,于是經(jīng)過排查,是因?yàn)閭鬟f消息的結(jié)構(gòu)體沒有考慮字節(jié)對齊的問題。隨手整理一下C語言中字節(jié)對齊的...

最近在做一個項(xiàng)目,遇到一個問題,運(yùn)行于ARM上的threadx在與DSP通信采用消息隊(duì)列的方式傳遞消息(最終實(shí)現(xiàn)原理是中斷 共享內(nèi)存的方式),在實(shí)際操作過程中發(fā)現(xiàn)threadx總是crash,于是經(jīng)過排查,是因?yàn)閭鬟f消息的結(jié)構(gòu)體沒有考慮字節(jié)對齊的問題。

隨手整理一下C語言中字節(jié)對齊的問題與大家一起分享。

一、概念

對齊跟數(shù)據(jù)在內(nèi)存中的位置有關(guān)。如果一個變量的內(nèi)存地址正好位于它長度的整數(shù)倍,他就被稱做自然對齊。比如在32位cpu下,假設(shè)一個整型變量的地址為0x00000004,那它就是自然對齊的。

首先了解什么位、字節(jié)、字

名稱英文名含義
bit1個二進(jìn)制位稱為1個bit
字節(jié)Byte8個二進(jìn)制位稱為1個Byte
word電腦用來一次性處理事務(wù)的一個固定長度

字長

一個字的位數(shù),現(xiàn)代電腦的字長通常為16,32, 64位。(一般N位系統(tǒng)的字長是N/8字節(jié)。)

不同的CPU一次可以處理的數(shù)據(jù)位數(shù)是不同的,32位CPU可以一次處理32位數(shù)據(jù),64位CPU可以一次處理64位數(shù)據(jù),這里的位,指的就是字長。

而所謂的字長,我們有時會稱為字(word)。在16位的CPU中,一個字剛好為兩個字節(jié),而32位CPU中,一個字是四個字節(jié)。若以字為單位,向上還有雙字(兩個字),四字(四個字)。

二、對齊規(guī)則

對于標(biāo)準(zhǔn)數(shù)據(jù)類型,它的地址只要是它的長度的整數(shù)倍就行了,而非標(biāo)準(zhǔn)數(shù)據(jù)類型按下面的原則對齊:  數(shù)組 :按照基本數(shù)據(jù)類型對齊,第一個對齊了后面的自然也就對齊了。聯(lián)合 :按其包含的長度最大的數(shù)據(jù)類型對齊。結(jié)構(gòu)體:結(jié)構(gòu)體中每個數(shù)據(jù)類型都要對齊。

三、如何限制定字節(jié)對齊位數(shù)?

1. 缺省

在缺省情況下,C編譯器為每一個變量或是數(shù)據(jù)單元按其自然對界條件分配空間。一般地,可以通過下面的方法來改變?nèi)笔〉膶鐥l件:

2. #pragma pack(n)

· 使用偽指令#pragma pack (n),C編譯器將按照n個字節(jié)對齊?!?使用偽指令#pragma pack (),取消自定義字節(jié)對齊方式。

#pragma pack(n) 用來設(shè)定變量以n字節(jié)對齊方式。n字節(jié)對齊就是說變量存放的起始地址的偏移量有兩種情況:

  1. 如果n大于等于該變量所占用的字節(jié)數(shù),那么偏移量必須滿足默認(rèn)的對齊方式
  2. 如果n小于該變量的類型所占用的字節(jié)數(shù),那么偏移量為n的倍數(shù),不用滿足默認(rèn)的對齊方式。
結(jié)構(gòu)的總大小也有一個約束條件,如果n大于等于所有成員變量類型所占用的字節(jié)數(shù),那么結(jié)構(gòu)的總大小必須為占用空間最大的變量占用的空間數(shù)的倍數(shù);否則必須是n的倍數(shù)。

3. __attribute

另外,還有如下的一種方式:· __attribute((aligned (n))),讓所作用的結(jié)構(gòu)成員對齊在n字節(jié)自然邊界上。如果結(jié)構(gòu)中有成員的長度大于n,則按照最大成員的長度來對齊?!?attribute ((packed)),取消結(jié)構(gòu)在編譯過程中的優(yōu)化對齊,按照實(shí)際占用字節(jié)數(shù)進(jìn)行對齊。

3. 匯編.align

匯編代碼通常用.align來制定字節(jié)對齊的位數(shù)。

.align:用來指定數(shù)據(jù)的對齊方式,格式如下:

.align?[absexpr1,?absexpr2]
以某種對齊方式,在未使用的存儲區(qū)域填充值. 第一個值表示對齊方式,4, 8,16或 32. 第二個表達(dá)式值表示填充的值。

四、為什么要對齊?

操作系統(tǒng)并非一個字節(jié)一個字節(jié)訪問內(nèi)存,而是按2,4,8這樣的字長來訪問。因此,當(dāng)CPU從存儲器讀數(shù)據(jù)到寄存器,IO的數(shù)據(jù)長度通常是字長。如32位系統(tǒng)訪問粒度是4字節(jié)(bytes), 64位系統(tǒng)的是8字節(jié)。當(dāng)被訪問的數(shù)據(jù)長度為n字節(jié)且該數(shù)據(jù)地址為n字節(jié)對齊時,那么操作系統(tǒng)就可以高效地一次定位到數(shù)據(jù),無需多次讀取,處理對齊運(yùn)算等額外操作。數(shù)據(jù)結(jié)構(gòu)應(yīng)該盡可能地在自然邊界上對齊。如果訪問未對齊的內(nèi)存,CPU需要做兩次內(nèi)存訪問。

字節(jié)對齊可能帶來的隱患:

代碼中關(guān)于對齊的隱患,很多是隱式的。比如在強(qiáng)制類型轉(zhuǎn)換的時候。例如:

unsigned?int?i?=?0x12345678;
unsigned?char?*p=NULL;
unsigned?short?*p1=NULL;

p=
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉
關(guān)閉