.NET 是不是将结构填充初始化为零?

Posted

技术标签:

【中文标题】.NET 是不是将结构填充初始化为零?【英文标题】:Does .NET initialize struct padding to zero?.NET 是否将结构填充初始化为零? 【发布时间】:2021-11-22 23:50:02 【问题描述】:

当 .NET 将结构初始化为零时,是否也会将填充也归零?

我问是因为我想知道对非托管结构进行按位比较的限制。

注意CanCompareBits 不仅检查类型是非托管的(!mt->ContainsPointers()),而且检查它是紧密打包的(!mt=>IsNotTightlyPacked)。请注意后者的双重否定:它要求类型 紧密包装。

// Return true if the valuetype does not contain pointer and is tightly packed
FCIMPL1(FC_BOOL_RET, ValueTypeHelper::CanCompareBits, Object* obj)

    WRAPPER_CONTRACT;
    STATIC_CONTRACT_SO_TOLERANT;

    _ASSERTE(obj != NULL);
    MethodTable* mt = obj->GetMethodTable();
    FC_RETURN_BOOL(!mt->ContainsPointers() && !mt->IsNotTightlyPacked());

FCIMPLEND

这段代码似乎暗示带有填充的结构不适合按位比较。这是什么时候,为什么?

我的假设是这与填充初始化有关,但也许还有更多事情要做。

【问题讨论】:

很可能是它根本没有定义所有场景中的填充区域应该发生什么 【参考方案1】:

结构填充被明确记录为不确定的。

来自https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code:

出于对齐目的,开头可能有未命名的填充 结构体、结构体内部和结构体末尾。这 用作填充的位的内容是不确定的。

这与 C/C++ 结构的文档相匹配,我认为这并非巧合。 ISO C99 标准规定:

当一个值存储在结构或联合类型的对象中时, 包括在成员对象中,对象表示的字节 对应于任何填充字节的数据采用未指定的值。”

所以回答你的问题:

“当 .NET 将结构初始化为零时,它是否也将填充清零?” - 未定义,所以你不能依赖它。

“什么时候是真的?” - 总是。

“为什么” - 如果这意味着“为什么填充没有初始化”,我只能推测:可能是出于性能原因,以及与 C/C++ 的互操作调用的兼容性。

【讨论】:

以上是关于.NET 是不是将结构填充初始化为零?的主要内容,如果未能解决你的问题,请参考以下文章

使用 memset 将结构体数组及其成员初始化为零

具有 char 数组的 C++ 结构以不寻常的方式初始化为零

将结构初始化为 0

全局对象内的内置类型的成员变量是不是已初始化为零?

Windows XP 会自动将数组初始化为零吗?

malloc()是否将分配的数组初始化为零?