C# Struct 内存对齐
结构体:
struct MyStruct0
{
public byte id;
public int val;
}
输出机构体的信息:
static void ShowStructInfo0()
{
unsafe
{
int size = sizeof(byte);
Console.WriteLine(" sizeof({0})={1} ", typeof(byte).FullName, size);
size = sizeof(int);
Console.WriteLine(" sizeof({0})={1} ", typeof(float).FullName, size);
size = sizeof(MyStruct0);
Console.WriteLine(" sizeof({0})={1} ", typeof(MyStruct0).FullName, size);
MyStruct0 myStruct = new MyStruct0() { id = 251, val = 12000 };
int i = 0;
byte* p = (byte*)&myStruct;
Console.WriteLine("myStruct0 start:Address:{0:X2} Value:{1:d}", (int)p, (byte)(*(p + i)));
Console.WriteLine();
for (i = 0; i < size; i++)
{
Console.WriteLine("Address:{0}={1:X} Value:{2:d}", i, (int)(p + i), (byte)(*(p + i)));
}
}
}
输出:
sizeof(System.Byte)=1
sizeof(System.Single)=4
sizeof(structApp.MyStruct0)=8
myStruct0 start:Address:12F440 Value:FB
Address:0=12F440 Value:FB
Address:1=12F441 Value:00
Address:2=12F442 Value:00
Address:3=12F443 Value:00
Address:4=12F444 Value:E0
Address:5=12F445 Value:2E
Address:6=12F446 Value:00
Address:7=12F447 Value:00
分析:
(1)对齐方式是按struct 中的最大类型来对齐,struct 每个字段的地址要求都是4的倍数。
0(id地址开始),3(占位),4(val地址开始)
(2)第1个字节来存放Byte,第2~4字节用来占位,第5~8字节用来存放 int
( 3 ) 由于 12000=16进制 2EE0,而Address[4]=E0,Address[5]=2E ,可以看出本机cpu是小端
2EE0=2*16*16*16+14*16*16+14*16+0*16=
问题:
Address:4=12F444 Value:E0
Address:5=12F445 Value:2E
就可以描述int,这两位用来干什么?
Address:6=12F446 Value:00
Address:7=12F447 Value:00
应该是负数的补码表示法会用到。
背景知识:
MSB (Most Significant Byte, 最高有效字节)为[Xw-1, Xw-2, ... Xw-8]; LSB (Least Significant Byte, 最低有效字节)为 [X7, X6, ..., X0]. 其余的字节位于MSB, LSB之间.
LSB和MSB谁位于内存的最低地址, 即谁代表该对象的地址? 这就引出了大端(Big Endian)与小端(Little Endian)的问题。
如果LSB在MSB前面, 既LSB是低地址, 则该机器是小端; 反之则是大端. DEC (Digital Equipment Corporation, 现在是Compaq公司的一部分)和Intel的机器一般采用小端. IBM, Motorola, Sun的机器一般采用大端. 当然, 这不代表所有情况. 有的CPU即能工作于小端, 又能工作于大端, 比如ARM, PowerPC, Alpha. 具体情形参考处理器手册.