简体   繁体   English

C# struct 或 struct[] 作为 memory 中连续结构的成员

[英]C# struct or struct[] as member of struct contiguous in memory

I am trying to understand how having a struct as a member of a struct would be stored in memory.我试图了解如何将结构作为结构的成员存储在 memory 中。 From what I understand, if we had a simple struct in memory, for example据我了解,如果我们在 memory 中有一个简单的结构,例如

struct Simple {
  int x;
  bool y;
}

then in if we initialized Simple s = new Simple() in memory we would see something contiguous like那么如果我们在 memory 中初始化Simple s = new Simple()我们会看到类似

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

so if we called sx then we would need to fetch s into the cpu and then have access to both x and y for operations since they are contiguous.因此,如果我们调用sx ,那么我们需要将s提取到 cpu 中,然后可以访问 x 和 y 进行操作,因为它们是连续的。

Now if we had an array of structs as a member现在,如果我们有一个结构数组作为成员

struct Simple {
  int x;
  Other[] otherArray;

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

struct Other {
  bool y;
}

if we did Simple s = new Simple() then in memory we would have如果我们做Simple s = new Simple()那么在 memory 我们会有

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

s.otherArray[0] would need to be fetched separately wherever it is stored in memory. s.otherArray[0]存储在 memory 中的任何位置都需要单独获取。 This is because the actual values within otherArray are not contiguously stored with x but the reference to the data is contiguous after x .这是因为otherArray中的实际值不与x连续存储,但对数据的引用在x之后是连续的。 If otherArray is initialized as Simple s = new Simple(1, new Simple[1]) , would otherArray data be stored contiguously after x or is otherArray always going to be a reference type either way (whether it's initialized in the struct constructor or not)?如果otherArray被初始化为Simple s = new Simple(1, new Simple[1])otherArray数据是否会在 x 之后连续存储,或者otherArray总是以任何方式作为引用类型(无论它是否在结构构造函数中初始化) )?

Finally, if we have a struct as a member of a struct最后,如果我们有一个结构体作为结构体的成员

struct Simple {
  int x;
  Other other;
}

this is where it is unclear for me.这是我不清楚的地方。 Is Simple s = new Simple() now stored as Is Simple s = new Simple()现在存储为

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

or is it或者是

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

In other words, is a struct as a member of struct stored contiguously with the struct or is it simply stored as some sort of address to the actual data of the other struct?换句话说,一个结构是作为结构的成员与结构连续存储的,还是简单地存储为另一个结构的实际数据的某种地址?

I would also appreciate any correction to my logic or further knowledge on how different types are stored in memory within struct as I am trying to generally understand how C# stores data in memory, thank you我还希望对我的逻辑进行任何更正或进一步了解不同类型如何存储在结构中的 memory 中,因为我试图大致了解 C# 如何将数据存储在 memory 中,谢谢,

would otherArray data be stored contiguously after x or is otherArray always going to be a reference type either way otherArray数据是否会在x之后连续存储,或者otherArray总是以任何方式作为引用类型

otherArray is always going to be a reference to an array object, even if it only has one element. otherArray始终是对数组 object 的引用,即使它只有一个元素。 The struct layout is a property of the struct type, not a property of particular struct values.结构布局是结构类型的属性,而不是特定结构值的属性。

is a struct as a member of struct stored contiguously with the struct or is it simply stored as some sort of address to the actual data of the other struct?结构是作为结构成员的结构与结构连续存储还是简单地存储为其他结构的实际数据的某种地址?

Structs are value types, so there is no "some sort of address to the actual data of the other struct".结构是值类型,因此没有“其他结构的实际数据的某种地址”。 That's what reference types would do.这就是引用类型的作用。 It's not contiguous necessarily, (but it is contiguous in the case of Other and Simple ) - it will follow the default alignment rules if you don't specify an explicit Pack or LayoutKind .它不一定是连续的,(但在OtherSimple的情况下是连续的) - 如果您未指定显式PackLayoutKind ,它将遵循默认的 alignment 规则。 See here for more info.请参阅此处了解更多信息。

Let's consider:让我们考虑一下:

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

struct Other
{
    public int y;
}

and the value:和价值:

var s = new Simple();
s.x = unchecked((int)0xabcdefab);
s.other.y = 0x12345678;

You'd expect the size of s be 8 bytes, and its value will contain the numbers 0xabcdefab and 0x12345678 :您希望s的大小为 8 个字节,其值将包含数字0xabcdefab0x12345678

// prints 8
Console.WriteLine(sizeof(Simple));
// in an unsafe block, prints 12345678ABCDEFAB
Console.WriteLine(Marshal.ReadInt64(new IntPtr(&s)).ToString("X"));

You can try adding more fields to Other , and see that sizeof(Simple) increases您可以尝试向Other添加更多字段,并看到sizeof(Simple)增加

Compare this to a reference type:将此与引用类型进行比较:

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

class OtherRef
{
    public int y;
}

You can't use & to get the address now, so here's a sharplab link to show that the other field is indeed an address, rather than the value you set it.您现在不能使用&来获取地址,所以这里有一个sharplab链接来显示other字段确实是一个地址,而不是您设置的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM