c# - .NET 是否将结构填充初始化为零?
问题描述
当 .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
此代码似乎暗示带有填充的结构不适合按位比较。什么时候是真的,为什么?
我的假设是这与填充初始化有关,但也许还有更多事情要做。
解决方案
结构填充被明确记录为不确定的。
从https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code:
出于对齐目的,在结构的开头、结构内和结构的末尾可能存在未命名的填充。用作填充的位的内容是不确定的。
这与 C/C++ 结构的文档相匹配,我认为这并非巧合。ISO C99 标准规定:
当一个值存储在结构或联合类型的对象中时,包括在成员对象中,对应于任何填充字节的对象表示的字节采用未指定的值。”
所以回答你的问题:
“当 .NET 将结构初始化为零时,它是否也将填充归零?” - 未定义,所以你不能依赖它。
“什么时候是真的?” - 总是。
“为什么” - 如果这意味着“为什么填充没有初始化”,我只能推测:可能是出于性能原因,以及与 C/C++ 的互操作调用的兼容性。
推荐阅读
- react-native - 如何从反应钩子中的自定义组件中获取参考?
- java - Android SparseArray 值比较
- gpio - Olimex Micro A20 某些 GPIO 在 18.0.06 上无法正常工作,但它们在 17.0.1 上工作
- cookies - Puppeteer 绕过 recaptcha 并以无头模式获取所有 cookie
- amazon-web-services - AWS Cognito 用户管理
- c# - 作业调度服务设计
- hive-metastore - Apache hive-metastore 独立显示错误“Kerberos 主体应包含 3 个部分:”
- mysql - 性能,要求 mysql 输出 CSV 格式 vs 解析结果并使用 App 进行转换
- laravel - Guzzle POST 请求:执行请求时需要的正文
- python - 如何在 R 中获得真正的价值