引 言
在嵌入式系統(tǒng)開發(fā)中,結構體作為一種常見的數(shù)據(jù)組織方式,在內(nèi)存中的布局方式對于程序性能和內(nèi)存占用具有重要影響。
1、為什么需要對齊?
在計算機內(nèi)存中,數(shù)據(jù)的存儲通常需要按照一定規(guī)則進行,這被稱為內(nèi)存對齊。內(nèi)存對齊的目的是為了提高訪問數(shù)據(jù)的效率,特別是對于硬件平臺而言。不同的處理器架構可能有不同的對齊要求。
2、不同的對齊方式
單字節(jié)對齊(Byte Alignment):每個數(shù)據(jù)類型從內(nèi)存的任意地址開始存儲,不需要對齊到特定字節(jié)邊界。
雙字節(jié)對齊(Half-Word Alignment):數(shù)據(jù)類型的變量必須從內(nèi)存的偶數(shù)地址開始存儲,即地址必須是2的倍數(shù)。
四字節(jié)對齊(Word Alignment):數(shù)據(jù)類型的變量必須從內(nèi)存的4字節(jié)邊界開始存儲,即地址必須是4的倍數(shù)。
3、結構體對齊示例
下面的C代碼示例演示了不同對齊方式在內(nèi)存中如何存儲一個簡單的結構體。
#include// 結構體定義struct Example {char a;int b;char c;};int main() {struct Example e;// 計算各成員的地址printf("Address of a: %p\n", &e.a);printf("Address of b: %p\n", &e.b);printf("Address of c: %p\n", &e.c);return 0;}

喜歡的讀者可以自行打印確定printf的輸出結果,觀察不同的地址有何規(guī)律。
4、結構體對齊的影響
(1)內(nèi)存占用
結構體對齊可以影響內(nèi)存的占用情況。考慮以下示例:
struct Example1 {char a;int b;char c;};struct Example2 {char a;char b;char c;};
結構體對齊也會影響數(shù)據(jù)的傳輸和存儲。當結構體作為數(shù)據(jù)包進行傳輸時,如果接收端和發(fā)送端的對齊方式不一致,可能需要進行字節(jié)序轉換,以確保數(shù)據(jù)的正確傳輸。這增加了編程的復雜性,因為程序員需要處理不同對齊方式可能導致的字節(jié)序問題。
下面是一個傳輸和存儲的C代碼示例,演示了在不同對齊方式下數(shù)據(jù)的傳輸和存儲:
#include#include// 結構體定義struct SensorData {uint16_t sensor1;uint32_t sensor2;} __attribute__((packed)); // 使用編譯器指令取消結構體對齊int main() {struct SensorData data;data.sensor1 = 0x1234;data.sensor2 = 0x56789ABC;// 數(shù)據(jù)存儲到內(nèi)存中uint8_t buffer[sizeof(struct SensorData)];memcpy(buffer, &data, sizeof(struct SensorData));// 模擬傳輸過程// 接收端假設數(shù)據(jù)是按照雙字節(jié)對齊方式接收struct SensorData* receivedData = (struct SensorData*)buffer;printf("Received sensor1: 0x%04X\n", receivedData->sensor1);printf("Received sensor2: 0x%08X\n", receivedData->sensor2);return 0;}
然后,我們將數(shù)據(jù)存儲到內(nèi)存中,并模擬了傳輸過程。接收端假設數(shù)據(jù)是按照雙字節(jié)對齊方式接收,但由于我們?nèi)∠藢R,需要進行字節(jié)序轉換。
1、外設寄存器對齊要求
在STM32這樣的嵌入式系統(tǒng)中,外設寄存器通常要求雙字節(jié)或四字節(jié)對齊,以確保寄存器的訪問性能和正確性。不滿足對齊要求可能導致未定義的行為或性能問題。
在STM32中,可以使用編譯器指令來實現(xiàn)對齊設置。例如,在Keil工程中,可以使用__align()指令來指定對齊方式。例如,要將一個結構體成員對齊到4字節(jié)邊界,可以這樣定義:
struct Example {char a;int b;char c;} __attribute__((aligned(4)));
2、內(nèi)存池分配
在嵌入式系統(tǒng)中,經(jīng)常使用內(nèi)存池來分配內(nèi)存。內(nèi)存池分配會確保分配的內(nèi)存塊是按照對齊要求進行的,以滿足處理器的要求。這可以防止未對齊內(nèi)存訪問,提高代碼的穩(wěn)定性和可靠性。
在STM32中,常用的內(nèi)存池分配庫如FreeRTOS提供了對齊設置的選項,以確保分配的內(nèi)存塊滿足處理器的要求。
3、DMA操作
嵌入式系統(tǒng)中常常使用DMA(直接內(nèi)存訪問)來進行數(shù)據(jù)傳輸。DMA操作通常要求數(shù)據(jù)緩沖區(qū)是雙字節(jié)或四字節(jié)對齊的。不滿足對齊要求可能導致DMA傳輸失敗或性能下降。
總之,作為嵌入式工程師,我們在編寫代碼時,需要根據(jù)目標硬件平臺的對齊要求。

END
→點關注,不迷路←