我正在努力理解将结构作为结构的成员如何存储在内存中。据我所知,如果我们在内存中有一个简单的结构,例如
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)
无论CCD_ 5存储在存储器中的哪个位置,都需要单独提取。这是因为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)
换句话说,一个结构是作为结构的成员与该结构连续存储的,还是只是作为另一个结构的实际数据的某种地址存储的?
我也很感激对我的逻辑进行任何更正,或者进一步了解不同类型如何在结构中存储在内存中,因为我正在努力理解C#如何在内存中存储数据,谢谢
otherArray
数据是在x
之后连续存储,还是otherArray
始终是的参考类型
otherArray
始终是对数组对象的引用,即使它只有一个元素。结构布局是结构类型的属性,而不是特定结构值的属性。
一个结构是作为与该结构相邻存储的结构的成员,还是只是作为另一个结构的实际数据的某种地址存储?
结构是值类型,因此不存在"到另一个结构的实际数据的某种地址";。这就是引用类型的作用。它不一定是连续的(但在Other
和Simple
的情况下是连续的(-如果不指定显式的Pack
或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;
您期望s
的大小为8个字节,其值将包含数字0xabcdefab
和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链接来显示other
字段实际上是一个地址,而不是您设置的值。