C#中结构体的内存大小与分配问题~求解

LaPoPvLe 2010-07-14 10:30:37
在与非托管代码的互操作时,有时会需要结构体传递结构体参数,因为两者之间存在内存分配上的差异,而坚决这个差异必须知道C#中的结构体内存分配与大小。
实验场景:
所有结构体均使用默认的:
StructLayoutAttribute(Value = LayoutKind.Sequential,Pack = 8)

结构体实际大小计算使用:
Marshal.SizeOf(typeof(StructName))


*下面的现象和问题假设在试验场景所用方法都正确下进行,如以上方式有误,请告知

先说说我的理解,结构体中的字段因为需要与Pack大小对齐,所以每次需保证字段的起始地址是Pack大小的整数倍。
//16字节
struct S1
{
sbyte b; //1
long l; //8
}


//16字节
struct S11
{
long l; //8
sbyte b; //1
}

因为long需要8个字节,而前面的sbyte只暂用1个字节,这时候需要额外的浪费7个字节使l字段偏移位置刚好在pack大小的倍数上。

但是下面的2个结构体,成员是一样的(除了顺序),但是大小却是不一样的。
struct S2 //32字节
{
int x; //4
double b; //8
double c; //8
byte a; //1
}

struct S3 //24字节
{
byte a; //1
int x; //4
double b; //8
double c; //8
}

问题1:猜想是a字段与x字段共同占用了第一个pack大小的空间。那么这与字段偏移量是pack大小的整数倍不就相矛盾了?求解释

还有一个现象:
struct S4 //12
{
sbyte s;//1
int i1; //4
int i2; //4
}

问题2:假设字段s与字段i1合并,那么根据前面的结构体S11,应该是16字节。字段i2(相对S11中的字段b)不足pack大小(8字节),补足。但实际为什么事12字节?求解释



...全文
994 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
LaPoPvLe 2010-07-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 wuyazhe 的回复:]

字节对齐
连续分配,不足8字节的对齐到8字节,如果剩下不足存放下一个变量,则补齐到8字节,下一个8字节开始保存。

C# code

struct S2 //32字节
{
int x; //4 :0~3
double b; //8 :8-4=4,不足以保存double的8字节,所以此处浪费4字节,double b位置:8~16
double c; //8 :……
[/Quote]
但是问题中的S4结构体,却是12字节的,按照补足原则应该是16字节吧(Pack为8字节下)。
兔子-顾问 2010-07-14
  • 打赏
  • 举报
回复
字节对齐
连续分配,不足8字节的对齐到8字节,如果剩下不足存放下一个变量,则补齐到8字节,下一个8字节开始保存。


struct S2 //32字节
{
int x; //4 :0~3
double b; //8 :8-4=4,不足以保存double的8字节,所以此处浪费4字节,double b位置:8~16
double c; //8 :17~24
byte a; //1 :25,但根据字节对齐原则,后面7个字节留空
}

struct S3 //24字节
{
byte a; //1 :0
int x; //4 :1~4
double b; //8 :8-5不足以保存double,则浪费3字节,double b位置:8~16
double c; //8 :17~24
}
assky124 2010-07-14
  • 打赏
  • 举报
回复
和系统有关吧
X86 系统最小分配内存为 4字节,就是Int32

可以用sizeof() 算一下结构体的长度
LaPoPvLe 2010-07-14
  • 打赏
  • 举报
回复
附上摘自C# 4.0 in nutshell中的一段描述,一直无法理解,很纠结。
For access speed, each field is placed at an offset that is a multiple of the field’s size.
That multiplier, however, is restricted to a maximum of x bytes, where x is the pack
size. In the current implementation, the default pack size is 8 bytes, so a struct comprising
a sbyte followed by an (8-byte) long occupies 16 bytes, and the 7 bytes following
the sbyte are wasted.

110,499

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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