关于结构体对齐(转载)
来源:互联网 发布:摩托罗拉gp328编程教程 编辑:程序博客网 时间:2024/06/05 12:21
#pragma pack(4)
class TestB
{
public:
int aa;
char a;
short b;
char c;
};
int nSize = sizeof(TestB);
这里nSize结果为12,在预料之中。
现在去掉第一个成员变量为如下代码:
#pragma pack(4)
class TestC
{
public:
char a;
short b;
char c;
};
int nSize = sizeof(TestC);
按照正常的填充方式nSize的结果应该是8,为什么结果显示nSize为6呢?
事实上,很多人对#pragma pack的理解是错误的。
#pragma pack规定的对齐长度,实际使用的规则是:
结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
也就是说,当#pragma pack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。
而结构整体的对齐,则按照结构体中最大的数据成员 和 #pragma pack指定值 之间,较小的那个进行。
具体解释
#pragma pack(4)
class TestB
{
public:
int aa; //第一个成员,放在[0,3]偏移的位置,
char a; //第二个成员,自身长为1,#pragma pack(4),取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。
short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。
char c; //第四个,自身长为1,放在[8]的位置。
};
这个类实际占据的内存空间是9字节
类之间的对齐,是按照类内部最大的成员的长度,和#pragma pack规定的值之中较小的一个对齐的。
所以这个例子中,类之间对齐的长度是min(sizeof(int),4),也就是4。
9按照4字节圆整的结果是12,所以sizeof(TestB)是12。
如果
#pragma pack(2)
class TestB
{
public:
int aa; //第一个成员,放在[0,3]偏移的位置,
char a; //第二个成员,自身长为1,#pragma pack(4),取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。
short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。
char c; //第四个,自身长为1,放在[8]的位置。
};
//可以看出,上面的位置完全没有变化,只是类之间改为按2字节对齐,9按2圆整的结果是10。
//所以 sizeof(TestB)是10。
最后看原贴:
现在去掉第一个成员变量为如下代码:
#pragma pack(4)
class TestC
{
public:
char a;//第一个成员,放在[0]偏移的位置,
short b;//第二个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[2,3]的位置。
char c;//第三个,自身长为1,放在[4]的位置。
};
//整个类的大小是5字节,按照min(sizeof(short),4)字节对齐,也就是2字节对齐,结果是6
//所以sizeof(TestC)是6。
当数据定义中出现__declspec( align() )时,指定类型的对齐长度还要用自身长度和这里指定的数值比较,然后取其中较大的。最终类/结构的对齐长度也需要和这个数值比较,然后取其中较大的。
可以这样理解, __declspec( align() ) 和 #pragma pack是一对兄弟,前者规定了对齐的最小值,后者规定了对齐的最大值,两者同时出现时,前者拥有更高的优先级。
__declspec( align() )的一个特点是,它仅仅规定了数据对齐的位置,而没有规定数据实际占用的内存长度,当指定的数据被放置在确定的位置之后,其后的数据填充仍然是按照#pragma pack规定的方式填充的,这时候类/结构的实际大小和内存格局的规则是这样的:
在__declspec( align() )之前,数据按照#pragma pack规定的方式填充,如前所述。当遇到__declspec( align() )的时候,首先寻找距离当前偏移向后最近的对齐点(满足对齐长度为max(数据自身长度,指定值) ),然后把被指定的数据类型从这个点开始填充,其后的数据类型从它的后面开始,仍然按照#pragma pack填充,直到遇到下一个__declspec( align() )。
当所有数据填充完毕,把结构的整体对齐数值和__declspec( align() )规定的值做比较,取其中较大的作为整个结构的对齐长度。
特别的,当__declspec( align() )指定的数值比对应类型长度小的时候,这个指定不起作用。
2.要注意区分__declspec是修饰类型还是修饰变量:
__declspec(align(8)) struct Str b;修饰的是变量b。其它地方定义的struct Str类型的变量将不受__declspec(align(8))影响。
__declspec(align(8)) struct Str {};修饰的是struct Str类型。所有该类型的变量都受__declspec(align(8))影响。
- 关于结构体对齐(转载)
- 结构体字节对齐---内存字节对齐(转载)
- 关于结构体对齐
- 【转载】结构体对齐问题
- 【转载】结构体字节对齐
- 结构体对齐的具体含义(#pragma pack) (转载)
- 结构体中字节对齐问题(转载)
- 关于结构体字节对齐
- 关于结构体字对齐
- 关于struct结构体对齐
- C++关于结构体对齐
- 关于c语言字节对齐(结构体)
- 关于结构体的长度问题(字节对齐)
- 关于结构体的大小(内存对齐)
- 关于字节对齐的问题(转载)
- 关于字节对齐【转载】
- 转载:关于字节对齐
- 关于C语言中的结构体对齐
- [android]Intent意图
- 关于串口的操作
- 根据上篇 自己改编的 当悬浮框在右边时,有一部分不显示的解决方案
- android中adb不是内部或者外部指令以及丢失adbwinapi.dll问题 的处理
- const、volatile、mutable的用法(转载)
- 关于结构体对齐(转载)
- Android 应用开发笔记 - Preface
- Android 打造自己的个性化应用(三):应用程序的插件化
- JQuery EasyUI 对话框的用法
- 不错的文章
- unrecognized command line option \"-fno-keep-inline-dllexport\"
- [线段树] hdu 3255 Farming#求体积并
- Java之运行时异常与编译时异常区别
- 【js与jquery】jquery对服务器端返回xml格式数据的解析和处理