C# 中的位运算符"~"

15

考虑以下单元测试代码:

    [TestMethod]
    public void RunNotTest()
    {

        // 10101100 = 128 + 32 + 8 + 4 = 172
        byte b = 172;

        // 01010011 = 64 + 16 + 2 + 1 = 83
        Assert.AreEqual(83, (byte)~b);
    }

这个测试通过了。但是如果没有字节转换,它会失败,因为"~"运算符返回的值是-173。为什么会这样?

2个回答

18

byte类型的数值进行按位取反时会自动提升为int类型,因为对于它们来说不存在二进制补码。

详见一元数值提升按位补码运算符

在对一个无符号8位数值10101100执行按位取反操作~时,它会被隐式地提升为32位有符号整数0...010101100。其补码为32位整数值1...101010011,即int类型的-173。将这个结果强制转换为byte类型会将它降级为无符号8位数值01010011,丢失了最高的24个比特位。最终的结果按无符号数值解释为83


10
字节数据类型真是个头疼的问题。 - BoltClock
@BoltClock:在C语言中,在32位机器上,无符号整数通常表示抽象代数环Z [4294967296]的成员,较小的无符号类型通常表现为环Z [256]和Z [65536]的成员; 然而,有符号值被认为代表数值量。 .NET框架假定所有整数类型都表示其可表示范围之外的数值量,大多数语言也是如此,只是C#可以执行涉及有符号或无符号32位或64位整数的某些操作,就好像它们表示代数环的成员一样。 - supercat
1
@BoltClock:在C语言中,较小的无符号类型会被提升为较大类型,但将其转换回较小类型通常会产生与使用较小代数环时相同的结果。然而,在C#中,如果代码在检查过的算术上下文中运行,则某些类型转换可能会失败。实际需要的是一种像Z[256]或Z[65536]那样的类型,并且可以很好地与“int”进行互操作。 - supercat

4
因为 ~ 返回一个整数。请参见 ~ 运算符 (C# 参考) (MSDN)
它仅对 int、uint、long 和 ulong 预定义,因此在使用它时对 byte 进行了隐式转换。

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