这个问题实在搞不明白

sunht 2001-12-11 04:00:55
typedef struct _DATA{

BYTE a[3];
BYTE b[3];
WORD c;
BYTE d;

DWORD e;
WORD f;
DWORD g;
char h[20];
char i[20];
char j[20];
char k[20];
BYTE l;

}DATA;
DATA data;
sizeof(data)=?
怎么等于108呢,我怎么算也不对呀(不论2BYTE对齐,还是4BYTE对齐)
平台:win2000+SP2 VC6+SP5
...全文
118 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
hillyx 2001-12-11
  • 打赏
  • 举报
回复
这个问题很有意思,masterz()的计算有一点问题,WORD的长度是两个字节,BYTE的长度是一个字节,也就是说 “WORD c; BYTE d;”一共应该占用4个字节,其他的都正确,结果当然是108了.
地平线 2001-12-11
  • 打赏
  • 举报
回复
常见问题,最好选择一个字节对齐,效率随低一点,不会在传递中出错.
如果不是一个字节对齐,那么与顺序有关.
以4字节对齐的结构为例:
struct STest1{
WORD w1;
DWORD dw1;
WORD w2
};
sizeof(SText) = 12;

struct STest2{
WORD w1;
WORD w2
DWORD dw1;

};

sizeof(STest2) = 8
woowindicevc 2001-12-11
  • 打赏
  • 举报
回复
来学习:)
joke100 2001-12-11
  • 打赏
  • 举报
回复

为了探究编译器的补位策略,将结构成员的顺序打乱如下:
typedef struct _DATA{
BYTE a[3];
BYTE b[3];
char h[20];
char i[20];
char j[20];
char k[20]; // 此处补2字节
WORD c;
WORD f;
DWORD e;
DWORD g;
BYTE l;
BYTE d; // 此处补2字节
}TESTDATA;
TESTDATA temp;
::memset(&temp, -1, sizeof(TESTDATA));
temp.a[0] = temp.a[1] = temp.a[2] = 'A';
temp.b[0] = temp.b[1] = temp.b[2] = 'A';
temp.d = 'd';
temp.e = 0;
temp.g = 0;
::memset(temp.h, 'h', 20);
::memset(temp.i, 'i', 20);
::memset(temp.j, 'j', 20);
::memset(temp.k, 'k', 20);
temp.l = 0;
int ii = sizeof(temp);
int jj = sizeof(TESTDATA);
TRACE1("\n%d", ii);
TRACE1("\n%d", jj);
结果结构的大小变为104,只补了4位,具体见上面的注释。。。
至此,我们可以得出这样的结论:

微软编译器对结构的对齐策略是,当出现数组成员时,在其后按对齐方式补齐,而对于非数组成员,采取立即补齐的方式。如上,a,b,两个数组成员各差1个字节,但其后紧跟的又是数组成员,所以补位延迟到数组成员结束处,即k[20]之后。

这种对数组成员的特殊补位策略显然能节省空间,例如当前后两个各自需要补位的数组成员做为一个整体不需补位则不补,,,效能提高。道理就在这儿!!!


joke100 2001-12-11
  • 打赏
  • 举报
回复
在文件头加上#pragma pack(1),一个字节对齐
当然是个办法,这样不会出现补位的问题,针对这种类型的传递也不会出问题。

其实最有意思的是编译器的补位策略。。。

tuggfox 2001-12-11
  • 打赏
  • 举报
回复
关注
tuggfox 2001-12-11
  • 打赏
  • 举报
回复
关注
tuggfox 2001-12-11
  • 打赏
  • 举报
回复
关注
rose_open 2001-12-11
  • 打赏
  • 举报
回复
关注
sunht 2001-12-11
  • 打赏
  • 举报
回复
在文件头加上#pragma pack(1),一个字节对齐

这样在别的计算机上运行或者接收来自其他程序发出的数据的时候会不会出问题?


caigzhi 2001-12-11
  • 打赏
  • 举报
回复
在文件头加上#pragma pack(1),一个字节对齐
joke100 2001-12-11
  • 打赏
  • 举报
回复

这个确实很有趣,我用vc做了一个测试,最后查看内存,得出微软编译器下面的结论。
typedef struct _DATA{
BYTE a[3];
BYTE b[3];
WORD c;
BYTE d; // 它后面补了3字节,以4字节对齐
DWORD e;
WORD f; // 它后面补了2字节,以4字节对齐
DWORD g;
char h[20];
char i[20];
char j[20];
char k[20];
BYTE l; // 它后面补了3字节,以4字节对齐
}TESTDATA;
TESTDATA temp;
::memset(&temp, -1, sizeof(TESTDATA));
temp.a[0] = temp.a[1] = temp.a[2] = 'A';
temp.b[0] = temp.b[1] = temp.b[2] = 'A';
temp.d = 'd';
temp.e = 0;
temp.g = 0;
::memset(temp.h, 'h', 20);
temp.l = 0;
int ii = sizeof(temp);
int jj = sizeof(TESTDATA);
TRACE1("\n%d", ii);
TRACE1("\n%d", jj);
计算本来的数据是100字节,加上补的8字节,形成108字节,但是对于数组成员却没有去为了对齐补位。

这款编译器的补位策略就是这样,只是不明白为什么要这样做?为什么c后面不补2位呢???



继续讨论
sunht 2001-12-11
  • 打赏
  • 举报
回复
你算错了吧,这样好象是112呀。不是108
masterz 2001-12-11
  • 打赏
  • 举报
回复
4BYTE对齐
typedef struct _DATA{

BYTE a[3]; //4 bytes
BYTE b[3]; //4 bytes
WORD c; //4 bytes
BYTE d; //4 bytes

DWORD e; //4 bytes
WORD f; //4 bytes
DWORD g; //4 bytes
char h[20];//20 bytes
char i[20];//20 bytes
char j[20];//20 bytes
char k[20];//20 bytes
BYTE l; //4 bytes

}DATA;
加起来等于108

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧