C/C++ __attribute__((__packed__)) 用法與範例

本篇 ShengYu 介紹 C/C++ __attribute__((__packed__)) 用法與範例。

現代的編譯器幾乎都會進行最佳化,所以有時候某資料結構佔用的 bytes 數可能不是你想像的,原因是因為編譯器會為了運行效能進行最佳化,如下列範例所示,

cpp-attribute-packed.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// g++ cpp-attribute-packed.cpp -o a.out
#include <iostream>
using namespace std;

struct CharChar { char c; char c2; };
struct CharCharInt { char c; char c2; int i; };
struct IntCharChar { int i; char c; char c2; };
struct CharIntChar { char c; int i; char c2; };
struct CharShortChar { char c; short s; char c2; };

int main() {
cout << "sizeof(CharChar) " << sizeof(CharChar) << '\n';
cout << "sizeof(CharCharInt) " << sizeof(CharCharInt) << '\n';
cout << "sizeof(IntCharChar) " << sizeof(IntCharChar) << '\n';
cout << "sizeof(CharIntChar) " << sizeof(CharIntChar) << '\n';
cout << "sizeof(CharShortChar) " << sizeof(CharShortChar) << '\n';

return 0;
}

我的平台輸出如下,值得注意的是 CharCharInt 手算的話應該為 6,但是編譯器進行最佳化時會變成 8,
而 CharIntChar 會因為順序關係而造成最佳化結果不同變成 12,
CharShortChar 手算的話應該為 4,但是編譯器進行最佳化時會變成 6,

1
2
3
4
5
sizeof(CharChar)       2
sizeof(CharCharInt) 8
sizeof(IntCharChar) 8
sizeof(CharIntChar) 12
sizeof(CharShortChar) 6

通常在跨平台或資料結構的網路通訊中會需要資料對齊,
那麼如果要一定讓它強制對齊的話呢?Windows 與 Linux / macOS 作法不同,
在 Windows 下是使用 #pragma pack,這寫法原本只適用於 Visual C++ 編譯器,但後來 GCC 為了相容性也加入了這個語法的支援,詳細用法可看這篇
在 Linux / macOS 下是這樣做,要加上 __attribute__((__packed__)),加在前或後都可以,適用於 GCC 編譯器,

cpp-attribute-packed.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// g++ cpp-attribute-packed2.cpp -o a.out
#include <iostream>
using namespace std;

struct __attribute__((__packed__)) CharChar {
char c;
char c2;
};

struct __attribute__((__packed__)) CharCharInt {
char c;
char c2;
int i;
};

struct IntCharChar {
int i;
char c;
char c2;
} __attribute__((__packed__));

struct CharIntChar {
char c;
int i;
char c2;
} __attribute__((__packed__)) charintchar;

typedef struct CharShortChar {
char c;
short s;
char c2;
} __attribute__((__packed__)) CharShortChar_t;

int main() {
charintchar.i = 123;
CharShortChar_t charshortchar;
cout << "sizeof(CharChar) " << sizeof(CharChar) << '\n';
cout << "sizeof(CharCharInt) " << sizeof(CharCharInt) << '\n';
cout << "sizeof(IntCharChar) " << sizeof(IntCharChar) << '\n';
cout << "sizeof(CharIntChar) " << sizeof(CharIntChar) << '\n';
cout << "sizeof(CharShortChar) " << sizeof(CharShortChar) << '\n';

return 0;
}

我的平台輸出如下,

1
2
3
4
5
sizeof(CharChar)       2
sizeof(CharCharInt) 6
sizeof(IntCharChar) 6
sizeof(CharIntChar) 6
sizeof(CharShortChar) 4

以上就是 C/C++ __attribute__((__packed__)) 的用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
如果你想學習 C/C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ pragma pack 用法與範例
C/C++ sizeof 用法與範例
C/C++ typedef 用法與範例
C/C++ define 用法與範例