游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3193|回复: 6

结构成员对齐(Structure Padding)具体是怎么做的

[复制链接]

51

主题

134

帖子

140

积分

注册会员

Rank: 2

积分
140
发表于 2008-2-17 22:09:00 | 显示全部楼层 |阅读模式
我在做一个虚拟机,我想知道结构成员对齐的具体算法,比如我知道字节边界为X字节,知道每个成员的大小
然后计算出结构体大小与每个成员的偏移位置。
顺便问下VC2005里默认字节边界为几个字节

2

主题

132

帖子

132

积分

注册会员

Rank: 2

积分
132
发表于 2008-2-18 21:09:00 | 显示全部楼层

Re:结构成员对齐(Structure Padding)具体是怎么做的

默认的是以结构自身的大小对齐的, 成员x的偏移只可能是sizeof(x)的倍数
且结构的大小为成员中最大成员的倍数,比如:


struct s0 { char a; char b; char c; };
各自都以1字节对齐,sizeof(s0) = 3


struct s1 { char a; int b; };
中 a 的偏移是0
b的大小为4字节,会以4字节对齐,所以b的偏移是4
sizeof(s1) = 8, 也就是说结构的第一字节是 a, 第2到4字节未使用,5到8字节是b


struct s2 { char a; char b; int c; short d; short e; __int64 f; int g; };
成员        大小        偏移
a        1        0
b        1        1
c        4        4
d        2        8
e        2        10
f        8        16
g        4        24

结构的大小似乎应该是 24+sizeof(g) = 24+4 = 28
但是结构中最大的成员是 __int64(8字节),所以整个结构大小是 32 字节,为最大成员大小8的4倍


另外数组的偏移是连续的,比如
struct s3 { char a; int b; short c[17]; };
成员        偏移
a        0
b        4
c[0]        8
c[1]        10
...        ...
c[15]        38
c[16]        40
结构的大小不是42字节而是44字节,要补齐最大成员int b(4字节)的整数倍


还有指针的问题,指针的大小全部是一样的,x86的程序指针为4字节,x64的程序指针全部为8字节
struct s4 { int a; short* b; };
比如这个结构编译为32位,sizeof(s4) = 8
成员        偏移        大小
a        0        4
b        4        4

编译为64位程序,sizeof(s4) = 16
成员        偏移        大小
a        0        4
b        8        8




需要改变对其方式可以使用 #pragma
比如
#pragma pack (1)        // 按1字节对齐
struct s5 { char a; int b; }
#pragma pack ()                // 恢复默认
那么 sizeof(s5) = 5,a的偏移为0,b为1

还可以使用
#pragma pack (push)         // 保存当前对齐方式
#pragma pack (n)        // 按 n 字节对齐, n只能为1, 2, 4, 8, 16
#pragma pack (pop)        // 恢复对齐方式



也可以单独用在某个成员上
struct s6
{
        char a;
#pragma pack (1)        // 按1字节对齐
        int b;
#pragma pack ()
        short c[17];
};
a偏移0
b偏移1
c[0]偏移6 (不是5),c[0]是要按照 sizeof(c[0])对齐的,c[1]之后的不需要对齐
c[16]偏移38
d偏移40
而原来最大的成员b按1字节对齐,所以按除此之外剩下最大成员c[0]的大小补齐
结构是42(最后补上了1字节),补齐c[0]的整数倍




还有一个关键字可以控制对齐
比如
__declspec( align(32) ) struct s7
{
        int a;
        __declspec( align(8) ) char b;
        __declspec( align(4) ) char c;
};
这样结构本身以32字节对齐,也就是说sizeof(s7)=32
其中b会以8字节对齐,c按4字节对齐
b的偏移为8,c为12

s7 x[2];
这样的数组,x[1] 和 x[0] 的地址相差32字节







最后,这个方法可以取得成员的偏移
struct s8
{
        short a;
        int b;
};
int offsetA = (int) &((s8*)0)->a;
int offsetB = (int) &((s8*)0)->b;



呵呵,明白否?希望对你有帮助。 [em13]

51

主题

134

帖子

140

积分

注册会员

Rank: 2

积分
140
 楼主| 发表于 2008-2-19 20:46:00 | 显示全部楼层

Re:结构成员对齐(Structure Padding)具体是怎么做的

很全 感谢楼上的。。。
不过我的具体实现看来要有些时间了

51

主题

134

帖子

140

积分

注册会员

Rank: 2

积分
140
 楼主| 发表于 2008-2-20 21:02:00 | 显示全部楼层

Re:结构成员对齐(Structure Padding)具体是怎么做的

默认以结构自身的大小对齐是什么意思?与设置边界字节无关吗?默认到底是几个字节,还是根据最大的那个

3

主题

137

帖子

151

积分

注册会员

Rank: 2

积分
151
QQ
发表于 2008-2-20 23:38:00 | 显示全部楼层

Re:结构成员对齐(Structure Padding)具体是怎么做的

pack的默认值在32位里好像是4吧?

2

主题

132

帖子

132

积分

注册会员

Rank: 2

积分
132
发表于 2008-2-21 21:54:00 | 显示全部楼层

Re: Re:结构成员对齐(Structure Padding)具体是怎么做的

nicehero: Re:结构成员对齐(Structure Padding)具体是怎么做的

默认以结构自身的大小对齐是什么意思?与设置边界字节无关吗?默认到底是几个字节,还是根据最大的那个


啊,不好意思,打错了,结构的对齐要根据结构自身的成员大小.
就看后面就是了,呵呵.

2

主题

44

帖子

44

积分

注册会员

Rank: 2

积分
44
发表于 2008-3-6 23:02:00 | 显示全部楼层

Re:结构成员对齐(Structure Padding)具体是怎么做的

内存字节对齐的问题,32bit系统通常来说是4字节对齐。

当然你也可是手动设置成1字节对齐活着别的,不过..........  嘿嘿 结果怎么样 天晓得
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-20 09:32

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表