为何使用StructLayout(LayoutKind.Sequential)的双布尔结构体占8字节?
.NET结构体中bool序列化的字节布局问题
问题分析
你的结构体序列化后得到01 00 00 00 01 00 00 00的原因,既不是单纯的内存填充,而是**.NET默认情况下将bool类型作为4字节(32位)整数处理,同时遵循小端序存储**,具体细节如下:
核心原因:.NET中bool的默认布局规则
- 在CLR的默认结构体布局(
LayoutKind.Sequential且未指定Pack值)中,bool类型的默认大小为4字节,而非1字节。这是CLR为了内存对齐效率做出的默认设定,和C++等语言的默认bool大小不同。 - 当bool值为
true时,其对应的整数值为1,小端序存储下就会呈现为01 00 00 00;两个bool成员就会依次占用4字节空间,最终得到8字节的十六进制结果。
为什么ChatGPT的结论不符
ChatGPT的说法混淆了不同语言的默认规则:在C++等语言中bool默认占1字节,但.NET的默认行为是将结构体中的bool按4字节对齐并存储,除非你显式修改序列化规则。
如何修改得到紧凑的1字节bool布局
如果希望两个bool紧挨着占用2字节,可以通过两种方式实现:
- 给每个bool成员添加
[MarshalAs(UnmanagedType.U1)]属性,强制将其序列化为1字节的无符号整数:[StructLayout(LayoutKind.Sequential)] public struct SystemServiceStatus { [MarshalAs(UnmanagedType.U1)] public bool isSystemUiOverlaid; [MarshalAs(UnmanagedType.U1)] public bool isInBackgroundExecution; } - 给结构体添加
Pack = 1的布局属性,强制所有成员按1字节对齐(会影响整个结构体的内存布局):[StructLayout(LayoutKind.Sequential, Pack = 1)] public struct SystemServiceStatus { public bool isSystemUiOverlaid; public bool isInBackgroundExecution; }
修改后,两个true值序列化后的十六进制就会是01 01。
内容的提问来源于stack exchange,提问作者Steinbitglis
相关产品推荐
相关产品推荐

