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

时间:2021-06-18 21:44:20

I don't understand the output from the following code:

我不明白以下代码的输出:

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);
}

Output:

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

Because byte is an 8-bit two's-complement signed integer, the binary representations with a 1 in the most significant bit are interpreted as negative values, which is why b becomes -128, which I'm totally fine with. I also understand that it's probably a good idea to keep the interpretation consistent when casting, as with i2. But shouldn't i3 and i4 have identical bit patterns and therefore map to identical int values?

因为byte是一个8位二进制补码有符号整数,所以在最高有效位中带有1的二进制表示被解释为负值,这就是为什么b变为-128,我完全没问题。我也明白,在投射时保持解释一致可能是个好主意,就像i2一样。但是i3和i4不应该有相同的位模式,因此映射到相同的int值?

7 个解决方案

#1


Sign extension is what is making i2 and i3 negative.

符号扩展是使i2和i3为负的原因。

In the expression (0 | b), b is promoted to an int, and sign extension occurs as part of this promotion.

在表达式(0 | b)中,b被提升为int,并且作为此促销的一部分发生符号扩展。

That's not happening in the expression assigned to i4. The constants 1 and 7 are already ints so there's no sign extension involved.

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

#2


In this line:

在这一行:

i3 = 0 | b;

The "b" variable is automatically promoted to int type with sign extension because of the | operator, so becomes (int)-128, i.e. 0xffffff80.

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

When "or"ed with zero, its still the same value, namely -128

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

#3


No, i4 is not a byte value, it's an int. That means that its sign bit is bit 31, not bit 7.

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

UPDATE: i3 is an int too, but it is initialized by extending a byte, so it keeps the sign from the byte value.

更新:i3也是一个int,但它是通过扩展一个字节来初始化的,所以它保持符号不受字节值的影响。

#4


i2 = (int) b;

i2 =(int)b;

i3 = 0 | b;

i3 = 0 | b;

the i3 statement is equivalent to:

i3语句相当于:

i3 = 0 | ((int) b) = 0 | i2 so naturally it is going to have the same value as i2

i3 = 0 | ((int)b)= 0 | i2很自然地它将具有与i2相同的值

#5


That's simple. i3 = 0 | b; gets evaluated like byte, then it is converted to int. Whereas i4 = 1 << 7; will evaluate value as int and assign it to int. So in the first case we get 10000000b cast to int from byte, which will give us -128. And in the second we just assign this value to int without cast, which gives us 128.

这很简单。 i3 = 0 | b;得到像字节一样的评估,然后它被转换为int。而i4 = 1 << 7;将值评估为int并将其分配给int。所以在第一种情况下,我们从byte获得10000000b转换为int,这将给出-128。在第二个我们只是将这个值赋给int而不使用强制转换,这给了我们128。

#6


If you want to get the unsigned value of the bit pattern in a byte:

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

b & 0xff

See also this old answer.

另见这个旧答案。

#7


In

i3 = 0 | b;

I'm guessing the 0 | b part is evaluated as a byte, and the results are then cast to an int, while in

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

i4 = 1 << 7;

the 1 << 7 part is already an int.

1 << 7部分已经是一个int。

The above guess has been pointed out in the comments to be wrong!

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

The correct version is: In the top expression, the b is already cast to an int with sign extension before the OR operation.

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

#1


Sign extension is what is making i2 and i3 negative.

符号扩展是使i2和i3为负的原因。

In the expression (0 | b), b is promoted to an int, and sign extension occurs as part of this promotion.

在表达式(0 | b)中,b被提升为int,并且作为此促销的一部分发生符号扩展。

That's not happening in the expression assigned to i4. The constants 1 and 7 are already ints so there's no sign extension involved.

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

#2


In this line:

在这一行:

i3 = 0 | b;

The "b" variable is automatically promoted to int type with sign extension because of the | operator, so becomes (int)-128, i.e. 0xffffff80.

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

When "or"ed with zero, its still the same value, namely -128

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

#3


No, i4 is not a byte value, it's an int. That means that its sign bit is bit 31, not bit 7.

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

UPDATE: i3 is an int too, but it is initialized by extending a byte, so it keeps the sign from the byte value.

更新:i3也是一个int,但它是通过扩展一个字节来初始化的,所以它保持符号不受字节值的影响。

#4


i2 = (int) b;

i2 =(int)b;

i3 = 0 | b;

i3 = 0 | b;

the i3 statement is equivalent to:

i3语句相当于:

i3 = 0 | ((int) b) = 0 | i2 so naturally it is going to have the same value as i2

i3 = 0 | ((int)b)= 0 | i2很自然地它将具有与i2相同的值

#5


That's simple. i3 = 0 | b; gets evaluated like byte, then it is converted to int. Whereas i4 = 1 << 7; will evaluate value as int and assign it to int. So in the first case we get 10000000b cast to int from byte, which will give us -128. And in the second we just assign this value to int without cast, which gives us 128.

这很简单。 i3 = 0 | b;得到像字节一样的评估,然后它被转换为int。而i4 = 1 << 7;将值评估为int并将其分配给int。所以在第一种情况下,我们从byte获得10000000b转换为int,这将给出-128。在第二个我们只是将这个值赋给int而不使用强制转换,这给了我们128。

#6


If you want to get the unsigned value of the bit pattern in a byte:

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

b & 0xff

See also this old answer.

另见这个旧答案。

#7


In

i3 = 0 | b;

I'm guessing the 0 | b part is evaluated as a byte, and the results are then cast to an int, while in

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

i4 = 1 << 7;

the 1 << 7 part is already an int.

1 << 7部分已经是一个int。

The above guess has been pointed out in the comments to be wrong!

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

The correct version is: In the top expression, the b is already cast to an int with sign extension before the OR operation.

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