结构指针(地址)和默认构造函数

lis*_*isz 10 c# c#-7.3

获取C#结构的地址是否会导致默认的构造函数调用?

例如,我有这样的结构:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct HEADER {
    public byte OPCODE;
    public byte LENGTH;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct S {
    public HEADER Header;
    public int Value;
}
Run Code Online (Sandbox Code Playgroud)

然后,当然,我不能这样做:

S s;                // no constructor call, so...
var v = s.Value;    // compiler error: use of possibly unassigned field 'Value'
Run Code Online (Sandbox Code Playgroud)

但是一旦我获得了结构的指针,我甚至可以在不使用指针的情况下读取它的字段,甚至是嵌入式结构域的字段:

S s;
S* ps = &s;
var v1 = ps->Value;        // OK, expected
var v2 = s.Value;          // OK!
var len = s.Header.LENGTH; // OK!
Run Code Online (Sandbox Code Playgroud)

那么,它是否以某种方式调用默认构造函数,或者 - 一旦我获取地址 - C#停止关注内存?

PS:无论如何,内存似乎都是零初始化的.

Hen*_*man 10

获取C#结构的地址是否会导致默认的构造函数调用?

不,它只是绕过编译器检查.

"使用可能未分配的字段"是一种保护您免受自身攻击的精确之处.但它很容易解决.在这种情况下,它似乎并不那么重要.

PS:无论如何,内存似乎都是零初始化的.

是的,这几乎总是(见下文)是.NET中的情况,使"默认构造函数调用"问题有点学术性.你的记忆发生了什么并没有与编译器警告紧密耦合.

  • 这是你的最后一行:事实并非如此 - 你可以通过IL hack来抑制locals init标志,而IIRC他们也计划通过属性来实现它 - 它在某些情况下显示出了有价值的信息.这个显示出可见差异的最明显的地方是"stackalloc"(堆栈空间不是零,就像通常那样),但绕过明确赋值的任何东西(如此处)也会做同样的事情.确实如此说*默认情况下*C#编译器总是擦除空间,但这与说.NET中总是如此(或者在C#中总是如此)的情况不同 (3认同)
  • 仅供参考:`System.Runtime.CompilerServices.SkipLocalsInitAttribute`; 你可能需要自己申报 - 请参阅:https://github.com/dotnet/corefx/issues/29026 (3认同)