内存对齐 结构体大小<pshpack2.h>等

下面这个结构体,用sizeof函数,得到的结果是4.为什么呢?

typedef struct _C
{
char a;
int b;
char c;
}C;

这是因为x86系统下,结构体会发生内存对齐操作,这是为了cpu存取数据速度快而设定的。

在上述的结构体中,块头最大的是int b,占4个字节,所以整个结构体就占4个字节。

typedef struct _D
{
char a;
double b;
char c;
}D;

而上面的结构体根据块头最大原则,就是得出sizeof(D)=24。呵呵,实际上的程序也证实了这一点。

对于我遇到的结构体,具体定义如下:

typedef struct tagBITMAPFILEHEADER {
                            WORD                        bfType;
                            DWORD                       bfSize;
                            WORD                        bfReserved1;
                            WORD                        bfReserved2;
                            DWORD                       bfOffBits;
} BITMAPFILEHEADER;

这个结构体实际的大小是2+4+2+2+4=14.而默认的时候,x86系统由于有内存对齐的操作,所以给他分配了4+4+(2+2)+4=16 bytes的大小,用sizeof(BITMAPFILEHEADER)=16可以证实这一点。但是问题就在这里,实际上bmp文件中,上述结构的大小为14bytes,如果按照下面的函数读取的话,就会发生错误。

fs.read((char*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER))

就会发生错误,这是为什么呢?下面自习分析这个数据结构:

typedef struct tagBITMAPFILEHEADER {
                            WORD                        bfType;                       //2B,
                            DWORD                       bfSize;                      // 4B,这个是块头最大的数据类型,4B,所以按照这个对齐,
                            WORD                        bfReserved1;//2B
                            WORD                        bfReserved2;//2B
                            DWORD                       bfOffBits;//4B
} BITMAPFILEHEADER;

在内存中分配的块如下:

内存对齐 <wbr>结构体大小<pshpack2.h>等

我们可以看到,第3,4字节是为了内存对齐给添加进去的,我们依次把14B的文件头信息添加到这里的话,就会使数据发生错位。另外,如果读取16B的话,那么就会读取到不应该读取的内容。

影响到文件指针的定位,和后面的读取。这就是我把wingdi.h中的BITMAPFILEHEADER结构体直接copy到我文件中不能使用的原因。为了查明这个原因,我仔细的看了wingdi.h文件,发现它在这个结构体定义的前后有#include <pshpack2.h>和#include <poppack.h>,查看这这些文件,才知道pshpack2.h实际上就是让结构体按照2B的大小对齐,而poppack则是上一个对于pack的设置失效。内部实际上是有一个栈在维护这个东鳌?/p>

于是我把自己的结构体前后也加上了#include <pshpack2.h>和#include <poppack.h>,发现一切OK了。呵呵,大功告成。

后来我又发现,还有pshpack1.h,pshpack4.h,pshpack8.h等文件,如果include的话,就表示要按照1B,4B,8B的字节顺序对齐。(实际上是这里指定的值和结构体中块头最大的值,两者取最小值)。

比如

#include <pshpack4.h>

typedef struct _B
{
char a;
short b;
char c;
}B;

对于上述的机构体,其大小仍然是6.仍然是按照2B的大小对齐的。

另外查阅pshpack1.h等文件,发现对于结构体内存对齐的控制是通过如下的pragma指令来实现的。

所以,也可以直接在程序中用下面的指令,但是推荐使用include头文件的方法。

#pragma ack(push,n)//n=1,2,4,8

#pragma pack(pop)

#pragma pack(n)     

#pragma pack()

另外,这样的操作是使得速度有所下降。所以不要滥用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值