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
45
46
47
|
#include <iostream> using namespace std; /** * 1 默认边界对齐 * 1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除(结构体对象作为结构体变量); * 2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍(变量的起始地址是该类型大小的整数倍), * 如有需要编译器会在成员之间加上填充字节(internal adding); * 3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍, * 如有需要编译器会在最末一个成员之后加上填充字节(trailing padding); * * 2 开启#pragma pack(n)之后将会关闭默认边界对齐 * 按照n的整数倍进行边界对齐 * 每个变量的起始地址都是n的整数倍 * * 3 位域 * 使用位域的主要目的是压缩存储,其大致规则为: * 1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止; * 2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍; * 3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式; * 4) 如果位域字段之间穿插着非位域字段,则不进行压缩; * 5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
// default : #***|####|####|##**|######## (e的起始地址必须是8的倍数) // #pragma pack(4) // 4+4+4+4+8=24 // #pragma pack(2) // 2+4+4+2+8=22 // #pragma pack(1) // 1+4+4+2+8=21 struct TestStruct { char a; // (variable) int *d; // 4 int b; // 4 int c:16; // (variable) double e; // 8 }; int main( int argc, char const *argv[]) { TestStruct testStruct; cout << sizeof (testStruct) << endl; // sizeof(testStruct.c) 错误:位域无法使用sizeof return 0; } |