C#中布尔值的二进制表示是什么?

13

我知道布尔值是1字节(8位)长的,但我想知道它的二进制表示是什么。 例如: 十进制 => 二进制 4 => 100 (0000 0100) 8 => 1000 (0000 1000) 布尔值 => ???

布尔值的二进制表示只有两个值:0和1。在计算机中,0通常代表假或错误,而1代表真或正确。因此,布尔值true的二进制表示为1,false的二进制表示为0。

我想不出除了某些强制要求的互操作场景之外,将布尔值视为整数是一个好主意的情况。 - SWeko
2
如果您想查询二进制值,可以使用BitArray。您不能使用watch,但是可以使用.Get[x]来获取每个位的值(true - 1,false - 0)。您还可以使用Convert.ToByte()将bool类型转换为byte。 - gooch
@gooch: Convert.ToByte(bool) 只是相当于 return (byte)(value ? 1 : 0);,因此并不能证明底层表示的任何内容。只是碰巧底层表示是相同的。 - LukeH
是的,没错。BitArray可以用于查询。而ToByte则超出了emm所要求的。 - gooch
@gooch:使用BitArray并不能证明bool的底层表示方式。BitArray使用int[]数组的各个位来存储其值,而Get方法则相当于执行return (requiredBitOfRequiredArrayElement == 1); - LukeH
5个回答

20

bool是C#语言中的一种内置基本类型。其具体实现细节是一个实现细节,不应过度关注。

根据《C# 4.0语言规范》第4.1.8节中的规定:

bool类型表示布尔逻辑量。类型bool的可能值为truefalse

bool类型与其他类型之间不存在标准转换。特别地,bool类型是明确而独立于整数类型的,bool值不能替代整数值,反之亦然。

在C和C++语言中,零整数或浮点数值,或空指针可以转换为布尔值false,非零整数或浮点数值,或非空指针可以转换为布尔值true。在C#中,这些转换通过将整数或浮点数值显式地与零比较,或者将对象引用显式地与null比较来实现。

如果我们深入了解对应类型在通用中间语言(CIL)中的规定,我们会发现CLI中的布尔类型占用1字节内存。在通用语言基础架构(CLI)规范中,第III部分,第1.1.2节中有所描述:

CLI布尔类型占用1字节内存。全零的位模式表示false,具有任意一个或多个设置比特的位模式(类似于非零整数)表示true的值。

然而,这是另一层面上的规定,在C#中您不必关心此细节;即使未来版本的CLI规范更改布尔类型的表示方式,或者C#编译器将C#中的bool映射到其他类型,您的C#代码仍将具有相同的语义。


1
.NET的内置基本类型,实际上C#的bool只是.NET System.Boolean的简写。 - Anthony Pegram
@Anthony Pegram:没错,但由于问题具体涉及C#,所以我只参考了C#规范。 - Dirk Vollmar

8

这是一段快速的代码,展示了bool在当前平台上的底层表示方式,无论它在哪个平台上运行:

var x = new NotAGoodIdea();

x.TheBool = true;
Console.WriteLine(x.TheByte);    // 1

x.TheBool = false;
Console.WriteLine(x.TheByte);    // 0

// ...

[StructLayout(LayoutKind.Explicit)]
public struct NotAGoodIdea
{
    [FieldOffset(0)]
    public bool TheBool;
    [FieldOffset(0)]
    public byte TheByte;
}

(请注意,虽然 1 看起来代表 true0 看起来代表 false,但这只是一种实现细节。您不应该依赖于此细节,或者假设它将在不同版本和/或实现之间保持一致,甚至不要假设当前平台总是使用相同的一致表示。) 编辑... ECMA CLI规范(第III部分,第1.1.2节)非常清楚地阐述了Boolean类型的允许表示方式:
引用:

1.1.2 Boolean数据类型

CLI布尔类型在内存中占用1字节。所有零的位模式表示false值。具有任何一个或多个设置位的位模式(类似于非零整数)表示true值。

看起来当前的 Microsoft CLR 遵循 ECMA 规范,允许多种表示方式的 true。以下示例显示了一行“False”(对于0)和 255 行“True”:

// re-use the NotAGoodIdea struct from the previous example
var x = new NotAGoodIdea();

for (int i = 0; i < 256; i++ )
{
    x.TheByte = (byte)i;
    Console.WriteLine(x.TheBool);
}

3
请注意,object.Equals()不认为两个内部不同的bool相等。这可能是object.Equals()的一个错误,但在健壮代码中几乎不可能遇到此问题。至少有一种情况,尽管CLI规范认为某些东西为true,但BCL却不是这样。 - Jon Hanna

6

我并不是要反驳0xA3的答案,但是如果你使用以下代码:

BitConverter.GetBytes(true);
BitConverter.GetBytes(false);

您将得到一个字节数组,其中包含{ 1 }{ 0 }。换句话说,二进制值将是0000000100000000

这并不意味着这就是.NET在内存中处理布尔值的方式 - 这只是它将它们转换为字节数组的方式。


0

几乎所有语言/环境(不仅限于.NET)都将true实现为等同于整数值1,而false等于0。1)

然而,有一个重要的例外,即VB6,它将true等于-1。这使得迁移到.NET时出现了很多困难,因为VB6的松散类型系统允许在同一表达式中混合整数和布尔值,而2 And True在VB6中与VB.NET中的含义不同。


1)尽管许多系统允许在布尔上下文中将任何非零数值隐式转换为true,但有些(特别是动态)语言甚至更进一步,认为除了特殊对象(例如None、空数组等),所有对象都等于true


3
在旧系统中,也使用了-1(0xffffff)和0。 - H H
5
我认为C语言将0视为false,而将其他任何东西都视为true? - Oded
@Oded:是的,true == ! false。指针转换也是如此。 - H H
@Oded:是的,这就是为什么我写“实现”而不是“处理”的原因。如果你在C++中写true(在C中是TRUE?我不知道……),它将被实现为值1。- 但请注意添加的备注。 - Konrad Rudolph

0
通常,布尔值通过false是所有零和true是其他任何值来表示。为了简单起见,由于二进制补码,通常使用-1(有符号整数类型的所有位都开启)来表示。

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