从计算结构变量字节大小的问题开始
问题:
在32位编译系统中,
typedef struct
{
int A;
char B;
}T_s;
请问T_s的长度为几个字节?
typedef struct
{
int A;
char B;
}T_s;
请问T_s的长度为几个字节?
答案:
题目不够严谨,跟编译器和编译选项有关的。
pc上的32位编译器一般缺省是4位对齐,所以长度会是8,此时在B后填充3字节,但对齐方式可以改的;
而有些嵌入系统的编译器缺省是不对齐的,所以长度为5。
pc上的32位编译器一般缺省是4位对齐,所以长度会是8,此时在B后填充3字节,但对齐方式可以改的;
而有些嵌入系统的编译器缺省是不对齐的,所以长度为5。
比如在vc中,
如果
#pragma pack(4) //缺省
则sizeof(T_s)等于8
如果
#pragma pack
则sizeof(T_s)等于5
而且和cpu有关,在有的机器上int不一定就是32位
要因结构对齐而定,对齐方式可以是1, 2, 4, 8, or 16
1对齐:5;2对齐:6;4对齐:8;8对齐:8;16对齐:8
1对齐:5;2对齐:6;4对齐:8;8对齐:8;16对齐:8
char是8位的,结构长度是8字节,在B之前没有对齐被位,但在B之后要补3个字节以便于在数组中把下一个元素的A对齐到4字节边界,当然这都是一般编译器在4字节对齐的情况下,如果某一编译器偏不这样实现,你也不能说它错了。因此如果我写一个编译器就把它的长度设为6字节,那么说它是6字节也正确。
其实字节对齐的知识对编写代码并没有什么帮助,并且也不应该利用这些知识。我以前曾经说过正确的态度是“不假设没有进行字节对齐,不假设编译时的对齐方式(包括可以不进行对齐)”。
计算结构变量的大小就必须讨论数据对齐问题。为了CPU存取的速度最快(这同CPU取数操作有关,详细的介绍可以参考一些计算机原理方面的书),C++在处理数据时经常把结构变量中的成员的大小按照4或8的倍数计算,这就叫数据对齐(data alignment)。这样做可能会浪费一些内存,但理论上速度快了。当然这样的设置会在读写一些别的应用程序生成的数据文件或交换数据时带来不便。MS VC++中的对齐设定,有时候sizeof得到的与实际不等。一般在VC++中加上#pragma pack(n)的设定即可.或者如果要按字节存储,而不进行数据对齐,可以在Options对话框中修改Advanced compiler页中的Data alignment为按字节对齐。
看一个例子:
将A写入二进制文件
#pragma pack (1)
struct A
{
char a;
int b;
};
文件
61 06 00 00 00#pragma pack (2)
struct A
{
char a;
int b;
};
文件
61 CC 06 00 00 00#pragma pack (4)
struct A
{
char a;
int b;
};
文件
61 CC CC CC 06 00 00 00#pragma pack (4)
struct A
{
char a;
int b;
};
文件
61 CC CC CC 06 00 00 00#pragma pack (8)
struct A
{
char a;
int b;
};
文件
61 CC CC CC 06 00 00 00该例子作者得出的结论:
结论是 实际的对齐长度 = [pack指定的对齐长度]和[struct中最长成员的长度]较小的一个。请各位指正。