是不是取了未初始化变量的地址就初始化为默认值?

Is it true that if the address of an uninitialized variable is taken, it is initialized to default value?

我有这个代码:

using System;

class Program
{
    unsafe static void f(void* v)
    {}
    static void Main()
    {
        int a;
        unsafe
        {
            f(&a);
        }
        Console.Write(a);
        Console.ReadKey();
    }
}

代码没有错误或异常。代码的输出是 0,而 a 没有明确给出任何初始值。代码是否正确,编译器是否将 a 隐式初始化为默认值?

在不安全的代码中,事情可能会变得奇怪。

首先,让我们看一下 C# 语言规范的 Variables 部分。

A variable must be definitely assigned <...> before its value can be obtained.

<...> variables are either initially assigned or initially unassigned. <...> An initially unassigned variable has no initial value. For an initially unassigned variable to be considered definitely assigned at a certain location, an assignment to the variable must occur in every possible execution path leading to that location.

“安全”C# 代码也是如此。

在不安全代码规范中,有一个address-of operator描述,它告诉我们:

The & operator does not require its argument to be definitely assigned, but following an & operation, the variable to which the operator is applied is considered definitely assigned in the execution path in which the operation occurs. It is the responsibility of the programmer to ensure that correct initialization of the variable actually does take place in this situation.

这正是你的情况。您将 address-of 运算符应用于 initially unassigned 变量,之后它被编译器视为 definitely assigned 变量 - 所以你即使在“安全”上下文中也可以使用它。

规范告诉我们,程序员负责变量的初始化。如果没有发生初始化,规范不保证实际变量中将存储什么值。

当前的 C# 编译器为此生成这样的 IL 代码:

.locals init (
    [0] int32 a
)

IL_0000: ldloca.s 0
IL_0002: conv.u
IL_0003: call void Namespace.Program::f(void*)

你看,有一个值类型的局部变量int32。 当前的 CLR (.NET Framework) 自动将所有局部变量初始化为零 - 这就是为什么变量的初始值将为 0,即使它没有在代码中初始化。

我不会依赖这个事实 - 据我所知,它不能保证并且可能会在其他实现中发生变化。