C# struct 或 struct[] 作为 struct 在内存中连续的成员

时间:2021-04-04 05:55:13

标签: c# memory struct memory-management

我试图了解如何将结构体作为结构体的成员存储在内存中。据我了解,如果我们在内存中有一个简单的结构,例如

struct Simple {
  int x;
  bool y;
}

然后,如果我们在内存中初始化 Simple s = new Simple(),我们会看到类似

s(0x01) --> 0x01(x - 32 bits data, y - 32 bits data) 

因此,如果我们调用 s.x,那么我们需要将 s 提取到 cpu 中,然后才能访问 x 和 y 进行操作,因为它们是连续的。

现在如果我们有一个结构数组作为成员

struct Simple {
  int x;
  Other[] otherArray;

  Simple(int input, Other[] otherInput)
  {
    x = input;
    otherArray = otherInput;
  }
}

struct Other {
  bool y;
}

如果我们做了 Simple s = new Simple() 那么在内存中我们就会有

s(0x01) --> 0x01(x - 32 bits, otherArray - 64 bit reference type) 

s.otherArray[0] 需要单独获取存储在内存中的任何位置。这是因为 otherArray 中的实际值没有与 x 连续存储,但对数据的引用在 x 之后是连续的。如果 otherArray 被初始化为 Simple s = new Simple(1, new Simple[1]),那么 otherArray 数据是在 x 之后连续存储还是 otherArray 总是将是一个引用类型(无论它是在结构中初始化构造函数与否)?

最后,如果我们有一个结构体作为结构体的成员

struct Simple {
  int x;
  Other other;
}

这是我不清楚的地方。 Simple s = new Simple() 现在存储为

s(0x01) --> 0x01(x - 32 bits data, other - 32 bits data of y as bool)

或者是

s(0x01) --> 0x01(x - 32 bits, other - some reference to the data containing y as bool)

换句话说,作为结构体成员的结构体是与结构体连续存储还是简单地存储为其他结构体的实际数据的某种地址?

我也希望能对我的逻辑进行任何更正或进一步了解不同类型如何存储在 struct 中的内存中,因为我试图大致了解 C# 如何在内存中存储数据,谢谢

1 个答案:

答案 0 :(得分:2)

<块引用>

otherArray 数据会在 x 之后连续存储还是 otherArray 始终是引用类型

otherArray 始终是对数组对象的引用,即使它只有一个元素。结构体布局是结构体类型的属性,而不是特定结构体值的属性。

<块引用>

一个结构体是作为结构体的成员与结构体连续存储还是简单地存储为其他结构体的实际数据的某种地址?

结构是值类型,因此没有“其他结构实际数据的某种地址”。这就是引用类型的作用。它不一定是连续的,(但在 OtherSimple 的情况下它是连续的)-如果您没有指定明确的 Pack 或 {{,它将遵循默认对齐规则1}}。有关详细信息,请参阅 here

让我们考虑:

LayoutKind

和价值:

struct Simple
{
    public int x;
    public Other other;
}

struct Other
{
    public int y;
}

您希望 var s = new Simple(); s.x = unchecked((int)0xabcdefab); s.other.y = 0x12345678; 的大小为 8 个字节,其值将包含数字 s0xabcdefab

0x12345678

您可以尝试向 // prints 8 Console.WriteLine(sizeof(Simple)); // in an unsafe block, prints 12345678ABCDEFAB Console.WriteLine(Marshal.ReadInt64(new IntPtr(&s)).ToString("X")); 添加更多字段,并看到 Other 增加

将此与引用类型进行比较:

sizeof(Simple)

您现在不能使用 struct Simple { public int x; public OtherRef other; } class OtherRef { public int y; } 来获取地址,所以这里有一个 sharplab 链接来表明 & 字段确实是一个地址,而不是您设置的值.

相关问题