为什么在C#中sizeof(bool) == sizeof(byte)?

5

可能重复:
在C#中布尔值的二进制表示是什么

根据MSDN文档sizeof关键字用于“获取非托管类型的字节大小”,原始类型被认为是非托管类型。如果我检查sizeof(bool),结果为1。

在我看来,使用布尔值只需要一点内存。我错了吗?使用Boolean值实际上需要一个完整的字节吗?为什么?


这个问题已经得到了回答:https://dev59.com/DHA75IYBdhLWcg3wW3y8#3335872。 - Adam
1
字节是可寻址内存的最小单位,因此即使只有一个位,至少也会发送一个字节。 - NoviceProgrammer
2
即使8个bool可以自动打包在一个字节中,而它们实际上并没有,1个bool仍然需要占用1个字节。 - harold
4个回答

14

出于性能方面的原因,它使用了一个完整的字节存储。

如果只使用一个比特,那么你要用其他7个比特做什么?很少有变量是布尔型,而其他变量可能不需要一个比特。因此,它只对其他布尔值有用。

例如,4字节整数。此外,许多较大的类型需要从适当的字节边界开始,以提高性能。例如,CPU 可能不允许您轻松地引用从任何地址开始的 4 字节地址(即地址可能需要被 4 整除)。

如果它使用一个比特的内存,这意味着其他7个比特可以用于其他布尔值,那么尝试使用这个布尔值将更加复杂。因为它不能直接寻址,所以在测试它是1还是0之前,需要先获取字节并提取比特。这意味着需要更多的指令-因此性能更慢。

如果您有许多布尔值,并且希望它们每个仅使用一个比特的内存,请使用 BitArray。这些是单比特的容器。它们的作用类似于布尔数组。


1
我可以在哪里了解更多关于这个的内容? - smartcaveman
高级语言可以屏蔽掉一些底层细节。我认为了解执行速度和某些实现方式的最佳方法是学习汇编语言。你不需要非常精通,但如果你知道有哪些指令可用等,你可能已经有足够的知识来弄清楚为什么要这样做。注意:汇编通常与机器码具有一对一的映射,因此你不需要过多担心机器码。 - ronalchn
我想阅读有关x86甚至x64架构的一些资料也会非常有用。这里有一些关于流水线、缓存、分支预测和其他细节的好信息。 - ronalchn
最后一个问题:如果您将应用程序中对布尔字段的每个引用都替换为对全局BitArray的访问调用,您会预期性能更好还是更差?(不用担心,这并不是我的意图,无论答案如何。我只是在尝试概念化。) - smartcaveman
它将占用更少的内存,但运行速度较慢。话虽如此,极不可能在内存或速度上有任何明显差异。这是因为你不太可能每秒使用那么多布尔值。只有当您想要调整大约1百万个布尔值时,它才可能开始产生明显影响。 - ronalchn
BitArray 可能非常慢。我们最终创建了一个自定义实现,它包装了字节数组并索引了单个位。 - Tim

7

字节是可寻址内存中最小的单位。.NET团队选择使用一个字节来存储bool类型数据,以简化实现过程。

如果您想更紧凑地存储大量位信息,可以查看BitArray


那么,我的结论是:在使用基于字节的枚举的位运算和使用bool之间,没有性能上的优势,我的结论正确吗? - smartcaveman
1
不,一个占用整个字节的布尔值可能会使用更多的内存,但对它的操作肯定会更快! - ronalchn
@ronalchn,为什么?- 具体来说,是针对检查特定标志的操作。 - smartcaveman
我在我的回答中提到了它 - 因为它不是“直接可寻址”的,所以您需要额外的指令来提取感兴趣的位以便读取、设置、比较或应用和/或/xor操作。 - ronalchn

4

是的,它需要一个完整的字节内存,因为这是最小可寻址的内存。

当然,可以想出一种方案,在同一个字节中放置多个布尔值,从而节省空间。对于更多的情况,这种解决方案的开销将比节省的空间更多。

如果您有大量位要存储,专用的位向量(例如Mark Byers提到的BitArray)可以节省宝贵的空间。


1

如果你认为1字节的数字值是1,那是因为sizeof。那么它怎么能说是1位呢?不可能,要么它向下取整并返回0,这是不可能的,要么它返回1,因为它占用了一个字节来保存,因为你不能以位为单位保存。

但是无论它是作为位还是字节进行管理,我不知道。

在C++中,你可以在变量名后面添加:1来表示它应该只有1位宽度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接