結構體對齊(64位Linux)
阿新 • • 發佈:2021-07-01
結構體對齊(64位Linux)
有關結構體對齊最關鍵的是要理清三個數值:
- 自身對齊值:變數的型別原有的預設對齊值,比如int是4,double是8,char是1
- 指定對齊值:通過#pragma pack或者attribute語法來顯式地i指定對齊值
- 有效對齊值:Min(指定對齊值,自身對齊值)
結構體或類的自身對齊值為其最大成員自身對齊值
下面上程式碼分析:
#include <unistd.h> #include <iostream> using namespace std; class unpacked { public: int a; char b; double c; }; class PackedByAttrribute { public: int a; char b; double c; } __attribute__((packed)); #pragma pack(2) class PackedByPragma { public: int a; char b; double c; }; #pragma pack() class Mix { public: unpacked a; PackedByAttrribute b; PackedByPragma c; int d; char e; double f; char g; }; //or: int main(int argc, char **argv) { unpacked A; PackedByAttrribute B; PackedByPragma C; Mix D; printf("unpacked: %d a:%p,b:%p,c:%p\n", sizeof(A), &A.a, &A.b, &A.c); printf("packed by attribute: %d a:%p,b:%p,c:%p\n", sizeof(B), &B.a, &B.b, &B.c); printf("packed by pragma pack: %d a:%p,b:%p,c:%p\n", sizeof(C), &C.a, &C.b, &C.c); printf("Mix: %d a:%p,b:%p,c:%p,d:%p,e:%p,f:%p,g:%p\n", sizeof(D), &D.a, &D.b, &D.c, &D.d, &D.e, &D.f, &D.g); return 0; }
輸出:
unpacked: 16 a:0x7fff41d5c9b0,b:0x7fff41d5c9b4,c:0x7fff41d5c9b8 packed by attribute: 13 a:0x7fff41d5c995,b:0x7fff41d5c999,c:0x7fff41d5c99a packed by pragma pack: 14 a:0x7fff41d5c9a2,b:0x7fff41d5c9a6,c:0x7fff41d5c9a8 Mix: 72 a:0x7fff41d5c9c0,b:0x7fff41d5c9d0,c:0x7fff41d5c9de,d:0x7fff41d5c9ec,e:0x7fff41d5c9f0,f:0x7fff41d5c9f8,g:0x7fff41d5ca00
分析
unpacked
gcc在64位下預設8位元組對齊,最後一個double需要8地址對齊,所以需要空多3位元組。這個類的有效對齊值為8,因為其成員的最大對齊值是8。
packedByAttribute
這是gcc的編譯器特有的語法,這樣指定相當於1位元組對齊,也就是pack(1),也有aligned(n)的語法。網路程式設計中時不時遇到,這樣做可以節省一點網路流量,忽略雙方機器的系統對齊情況。其大小就是各成員大小相加。
packedByPack(2)
指定2位元組對齊,所以最後一個double變數僅需要空一個位元組便可實現2位元組對齊,其有效對齊值為2。
Mix
僅需要注意最後的char變數因為整個類的有效對齊值為8,所以整個類的大小為其對齊值的整數倍,所以還要補充7個位元組對齊,各個成員在Mix中都根據自己的有效對齊值來對齊。