Java:为什么二进制OR不按预期工作(参见下面的代码)?

时间:2009-04-21 08:45:45

标签: java binary

我不理解以下代码的输出:

public static void main(String[] args) {
    int i1, i2, i3, i4;
    byte b;
    i1 = 128;
    b = (byte) i1;
    i2 = (int) b;
    i3 = 0 | b;
    i4 = 1 << 7;
    System.out.format("i1: %d   b: %d   i2: %d   i3: %d   i4: %d\n", i1, b, i2, i3, i4);
}

输出:

i1: 128   b: -128   i2: -128   i3: -128   i4: 128

因为byte是一个8位two's-complement有符号整数,所以最高有效位为1的二进制表示被解释为负值,这就是b成为{{}的原因。 1}},我完全没问题。我也明白,在投射时保持解释一致可能是个好主意,就像使用-128一样。但是,i2i3不应该具有相同的位模式,因此会映射到相同的i4值吗?

7 个答案:

答案 0 :(得分:5)

在这一行:

i3 = 0 | b;

由于int运算符,“b”变量会自动提升为带有符号扩展名的|类型,因此变为(int)-128,即0xffffff80

当“或”ed为零时,它仍然是相同的值,即-128

答案 1 :(得分:4)

不,i4不是字节值,而是int。这意味着它的符号位是第31位,而不是第7位。

更新i3也是int,但是通过扩展byte进行初始化,因此它会保留byte的符号}值。

答案 2 :(得分:4)

签名扩展使得i2i3为负。

在表达式(0 | b)中,b被提升为int,并且此促销中会出现符号扩展名。

分配给i4的表达式中没有发生这种情况。常量17已经是整数,因此不会涉及符号扩展。

答案 3 :(得分:2)

i2 = (int) b;

i3 = 0 | b;

i3语句相当于:

i3 = 0 | ((int) b) = 0 | i2所以很自然它会与i2

具有相同的价值

答案 4 :(得分:1)

i3 = 0 | b;

我猜0 | b part被评估为一个字节,然后将结果转换为int,而在

i4 = 1 << 7;

1&lt;&lt; 7部分已经是一个int。

上述猜测已经在评论中指出是错误的!

正确的版本是:在顶部表达式中,在OR操作之前,b已经被转换为带符号扩展名的int。

答案 5 :(得分:1)

这很简单。 i3 = 0 | b;评估为byte,然后转换为int。而i4 = 1 << 7;会将值评估为int,并将其分配给int。因此,在第一种情况下,我们会从10000000bint投放byte,这会给我们-128。在第二个中,我们只是将此值分配给int而不进行强制转换,这样我们就可以128

答案 6 :(得分:1)

如果要在字节中获取位模式的无符号值:

b & 0xff

另见this old answer