今天,用VC做一个简单的工具,向下位机设备传送一些数据。碰到了一个以前没有注意的问题。那就是内存对齐方式对sizeof的影响。上网浏览了http://blog.vckbase.com/zhangjw_cn/archive/2005/08/09/10701.html的说明,一下子明白了问题的缘由。记录整理一下,便于以后查阅,同时也便于碰到类似问题而不熟悉的朋友了解。 假定如下的数据结构:
... {
char a;
double b;
} ;
我原本以为sizeof(struct1)是9(1+8)。
using std::cout;
using std::endl;
struct struct1
... {
char a;
double b;
} ;
int main()
... {
int nSize = sizeof(struct1);
cout << "Sizeof struct1 is " << nSize << endl;
return 0;
}
输出的结果:
Sizeof struct1 is 16
原来,在VC中,默认的字符对齐方式是8。按ALT+F7,在弹出的Project Settings对话框中,C/C++标签页中可以看到工程当前的内存对齐方式:
显然,当前的对齐方式为8。这正是为什么sizeof(struct1)等于16的原因。
Win32下,在struct1中a的大小为1byte,不是8的倍数,所以VC额外填充了7个空字节,满足8字节对齐,而b为double类型,其大小为8byte。这样sizeof(struct1)正好等于16.
我们可以设定对齐方式为1、2、4、8、16中的任意一种。结果显然如下:
1 Bytes : 1+8 = 9
2 Bytes: 1+1+8=10
4 Bytes:1+3+8=12
8 Bytes:1+7+8=16
16 Bytes:(1+8=9(8<9<16))= 16
在工程中设置对齐方式对整个工程都是有效的。在应用程序中,可以通过使用#pragma预处理指令设定某个结构的对齐方式。
如可以这样定义一个结构体:
#pragma pack(1) // 按字节对齐,实际大小
typedef _MYST
... {
char a;
double b;
} MYST;
#pragma pack(pop) // 恢复对齐状态
因此下面的程序(Win32+VC6):
using std::cout;
using std::endl;
// 1位字节对齐
#pragma pack(push)
#pragma pack(1)
typedef struct _STRUCT1
... {
char a;
double b;
} STRUCT1;
#pragma pack(pop)
// 4位字节对齐
#pragma pack(push)
#pragma pack(4)
typedef struct _STRUCT2
... {
char a;
double b;
} STRUCT2;
#pragma pack(pop)
// 8位字节对齐
#pragma pack(push, 8)
typedef struct _STRUCT3
... {
char a;
double b;
} STRUCT3;
int main()
... {
cout << "sizeof STRUCT1 is " << sizeof(STRUCT1) << endl;
cout << "sizeof STRUCT2 is " << sizeof(STRUCT2) << endl;
cout << "sizeof STURCT3 is " << sizeof(STRUCT3) << endl;
return 0;
}
运行输出的结果为:
sizeof STRUCT1 is 9
sizeof STRUCT2 is 12
sizeof STURCT3 is 16