更改C編譯器的預設位元組對齊方式__align(),__attribute((aligned-(n))),#pragma-pack(n)
阿新 • • 發佈:2020-10-05
在預設情況下,C編譯器為每一個變數或是資料單元按其自然對界條件分配空間。一般地,可以通過下面的方法來改變預設的對界條件:
- 使用偽指令#pragma pack (n),C編譯器將按照n個位元組對齊。
- 使用偽指令#pragma pack (),取消自定義位元組對齊方式。
另外,還有如下的一種方式:
- __attribute((aligned (n))),讓所作用的結構成員對齊在n位元組自然邊界上。如果結構中有成員的長度大於n,則按照最大成員的長度來對齊。
- attribute ((packed)),取消結構在編譯過程中的優化對齊,按照實際佔用位元組數進行對齊。
例子:
struct cmd1_ { uint32_t d1 = 11; }; struct cmd2_ { uint8_t u8_d1 = 21; uint8_t u8_d2 = 22; uint16_t u16_d3 = 23; uint32_t u32_d4 = 24; uint64_t u64_d5 = 25; uint64_t u64_d6 = 26; uint32_t u32_d7 = 27; uint32_t u32_d8 = 28; }; struct fw_cmd_ { struct cmd1_ cmd1; struct cmd2_ cmd2; }; struct fw_cmd_ fw_cmd;
猜猜sizeof(fw_cmd)=? 應該是4+1+1+2+4+8+8+4+4 = 36實際:
強制按4位元組對齊:
#include <iostream> #include <stdint.h> #pragma pack(4) struct cmd1_ { uint32_t d1 = 11; }; struct cmd2_ { uint8_t u8_d1 = 21; uint8_t u8_d2 = 22; uint16_t u16_d3 = 23; uint32_t u32_d4 = 24; uint64_t u64_d5 = 25; uint64_t u64_d6 = 26; uint32_t u32_d7 = 27; uint32_t u32_d8 = 28; }; struct fw_cmd_ { struct cmd1_ cmd1; struct cmd2_ cmd2; }; int main(int argc, char** argv) { struct fw_cmd_ fw_cmd; printf("sizeof(uint8_t):%d\r\n", sizeof(uint8_t)); printf("sizeof(uint16_t):%d\r\n", sizeof(uint16_t)); printf("sizeof(uint32_t):%d\r\n", sizeof(uint32_t)); printf("sizeof(uint64_t):%d\r\n", sizeof(uint64_t)); printf("sizeof(fw_cmd):%d\r\n", sizeof(fw_cmd)); return 0; }
輸出: