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 个字节。您可以使用BitVector32BitArray 或简单的按位算术来减少此开销。作为变量,我似乎记得它们占用 4 个字节(基本上处理为 int = Int32)。

例如,以下将i 设置为4:

struct Foo

    public bool A, B, C, D;

static unsafe void Main()

    int i = sizeof(Foo);

【讨论】:

请注意,尝试优化这些东西很可能为时过早。除非您主要对大量布尔数据进行操作,否则它们不会成为任何内存问题的原因。 但是如果你使用 Marshal.SizeOfFoo 的实例,它返回 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? 的大小的?我不能使用sizeofMarshal.SizeOf 返回4。 我创建了一个浮点数?[] 和一个浮点数[]。在每一步之前和之后,我调用了 GC.GetTotalMemory()。如果您在调用 GetTotalMemory 之前调用 GC.Collect() 几次,您将看到分配所消耗的实际内存量,包括任何对齐,而不仅仅是数据元素本身的大小。

以上是关于C#中的原始布尔大小的主要内容,如果未能解决你的问题,请参考以下文章

为啥没有定义 Java 的布尔原始大小?

为啥没有定义 Java 的布尔原始大小?

将 SQL Server 中的 SELECT 中的布尔值转换为 C# 中的布尔值?

c#中的布尔属性

可空布尔作为 C# 中的三态变量

如何在 Windows 窗体 C# 中单击按钮通过 DataGridView 更新数据库中的布尔字段