下面代码的输出结果是:
#include
using namespace std;
#pragma pack(4)
struct T{
char a;
short b;
char c;
};
#pragma pack()
int main()
{
cout << sizeof(T) << endl;
return 0;
}
A. 4 B. 5 C. 8 D. 6
结构体成员按照定义时的顺序依次存储在连续的内存空间,但是结构体的大小并不是简单的把所有成员大小相加,而是遵循一定的规则,需要考虑到系统在存储结构体变量时的地址对齐问题。
例1:
struct T{
char a;
short b;
char c;
};
【分析】
第一个成员char a
的偏移量为0
;
第二个成员short b
的偏移量为前一个成员的偏移量+前一个成员的大小,即0 + 1 = 1
,因1不是该成员大小2
的整数倍,所以需要调整到2
(最小倍数),所以第二个成员的偏移量为2
;
第三个成员char c
的偏移量为第二个成员的偏移量+第二成员的大小2 + 2 = 4
, 4
是其大小1
的整数倍,所以第三个成员的偏移量为4
;
所以该结构体大小sizeof(T)
的计算结果为最后一个成员的偏移量加上其大小即4 + 1 = 5
,但5不是所有成员大小(1, 2, 1)
的整数倍,所以需要补齐到**6
**。
注:偏移量可以理解为结构体成员相对于结构体的起始地址
例2:嵌套的结构体
struct T
{
short a;
struct
{
char b;
int c;
} tmp;
int d;
};
对于嵌套的结构体,应该将其展开,规则变化为:
【分析】
第一个成员short a
的偏移量为0
;
第二个成员char b
, 其偏移量本是前一个成员的偏移量+前一个成员的大小, 即0 + 2 = 2
,但它又是tmp结构体的第一个成员,其偏移量应该是tmp结构体中最大成员int c
大小4
的整数倍, 所以应该调整到4;
第三个成员int c
,偏移量为4 + 1 = 5
,调整到其自身大小整数倍8;
第四个成员int d
,偏移量为8 + 4 = 12
,已经是自身大小整数倍,无需调整;
所以该结构体大小sizeof(T)
的计算结果为最后一个成员的偏移量加上其大小即12 + 4 = 16
,16
是展开后所有成员大小(2, 1, 4, 4)
的整数倍,所以无需再调整。
例3:包含数组成员的结构体
struct T
{
float f;
char p;
int arr[3];
};
将数组看成一个结构体,其中所有成员均为该数组类型变量,同样展开计算。
【分析】
第一个成员float f
偏移量为0;
第二个成员char p
偏移量为0 + 4 =4
,是其大小1
的整数倍,无需调整;
第三个成员int arr[3]
为数组,展开为三个int
类型成员计算
…
最后一个成员的偏移量为16
所以该结构体大小sizeof(T)
的计算结果为最后一个成员的偏移量加上其大小即16 + 4 = 20
,16
是展开后所有成员大小(4, 1, 4)
的整数倍,所以无需再调整。
编译器中提供了#pragma pack(n)
来设定变量以n字节对齐
方式。n字节对齐
就是说变量存放的起始地址的偏移量有两种情况:
n
大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式n
小于该变量的类型所占用的字节数,那么偏移量为n
的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:
n
大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;n
的倍数。总结一下,就是两条判断原则:
每个成员的偏移量必须是**x
**的倍数, x = min(n,该成员大小)
结构体的总大小必须是**y
**的倍数, y = min(n,占用空间大的变量的字节数)
例:
#pragma pack(4)
struct T{
char a;
short b;
char c;
};
#pragma pack()
【分析】
n = 4
;
第一个成员char a
,其偏移量为0(无论n的值和第一个成员的类型,第一个成员的偏移量总是0);
第二个成员short b
, 计算x = min(4, 2) = 2
,其偏移量为第一个成员的偏移量+第一个成员的大小,即0 + 1 = 1
,因为1
不是x的倍数,所以偏移量调整为2
;
第三个成员char c
,计算x = min(4, 1) = 1
的偏移量为第二个成员的偏移量+第二成员的大小,即2 + 2 = 4
, 4
是x的整数倍,所以第三个成员的偏移量为4
;
计算y = min(4, max(1, 2, 1)) = 2
, 该结构体大小sizeof(T)的计算结果为最后一个成员的偏移量加上其大小即4 + 1 = 5
,但5
不是y的整数倍,所以需要补齐到6
。