C#中的原始布尔大小
Posted
技术标签:
【中文标题】C#中的原始布尔大小【英文标题】:Primitive Boolean size in C# 【发布时间】:2011-01-19 11:09:41 【问题描述】:C# 中的布尔变量如何存储在内存中?也就是说,它们是否存储为一个字节而其他 7 位被浪费了,或者在数组的情况下,它们是否被分组为 1 字节的布尔块?
这回答了关于 Java (Why is Java's boolean primitive size not defined?) 的相同问题。 Java 和 C# 在这方面是否相同?
【问题讨论】:
关于“和其他 7 位被浪费” - 是的。虽然这取决于语言如何它们被浪费:C# 值true
用零浪费了 7 个额外的位,而 VB.NET 值 true
用 1 浪费了它们(尽管你永远不必知道,. NET 将所有非零都视为真)。
我从上面撤回我的声明:当我编写一个类型来演示该行为时,我发现当前的 VB.NET (.NET 4.8) 也只为true
设置最低位。 (如果过去的行为不同,或者我完全弄错了,我没有进一步调查 - 如果您了解更多,请随时发表评论)。我可以通过我的测试确认“.NET 将所有非零都视为真实”的声明。
【参考方案1】:
在 C# 中,当然 bits 默认不打包,因此多个 bool fields 将占用 1 个字节。您可以使用BitVector32
、BitArray
或简单的按位算术来减少此开销。作为变量,我似乎记得它们占用 4 个字节(基本上处理为 int
= Int32
)。
例如,以下将i
设置为4:
struct Foo
public bool A, B, C, D;
static unsafe void Main()
int i = sizeof(Foo);
【讨论】:
请注意,尝试优化这些东西很可能为时过早。除非您主要对大量布尔数据进行操作,否则它们不会成为任何内存问题的原因。 但是如果你使用Marshal.SizeOf
和 Foo
的实例,它返回 16,无论是类成员还是局部变量(根据 Stilgar 的回答)。
@Andrew 坦率地说,Marshal
返回的内容在很大程度上是不相关的。除非您实际使用编组,否则就是这样。
@mireazma 如果你正在处理状态标志,你最好的选择是标志枚举 - 然后它们将被打包在位级别
4 bool 使用 16 个字节与结构体的包大小有关。如果你使用[StructLayout(LayoutKind.Sequential, Pack = 1)]
,它应该被打包成4个字节...【参考方案2】:
在 C# 中,它们在数组或字段中存储为 1 个字节,但有趣的是,当它们是局部变量时,它们是 4 个字节。我相信 bool 的 1 字节是在 .NET 文档中与 Java 不同的某个地方定义的。我想局部变量的 4 个字节的原因是为了避免在寄存器中读取 32 位时屏蔽这些位。 sizeof 运算符仍然显示 1 个字节,因为这是唯一相关的大小,其他一切都是实现细节。
【讨论】:
浮动?被存储为浮点数和布尔值,在这种情况下,布尔值也以 4 个字节结束(浮点数?浮点数需要 8 个字节,而浮点数需要 4 个字节)。在这种情况下,它可能会将布尔值对齐到 4 个字节,因为它与数组中的浮点数配对。 @John,你是如何测量float?
的大小的?我不能使用sizeof
和Marshal.SizeOf
返回4。
我创建了一个浮点数?[] 和一个浮点数[]。在每一步之前和之后,我调用了 GC.GetTotalMemory()。如果您在调用 GetTotalMemory 之前调用 GC.Collect() 几次,您将看到分配所消耗的实际内存量,包括任何对齐,而不仅仅是数据元素本身的大小。以上是关于C#中的原始布尔大小的主要内容,如果未能解决你的问题,请参考以下文章