Java:为什么二进制OR不按预期工作(参见下面的代码)?
我不明白以下代码的输出:
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: %db: %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位二进制补码有符号整数,所以在最高有效位中带有1的二进制表示被解释为负值,这就是为什么b
变为-128
,我完全没问题。 我也明白,在投射时保持解释一致可能是个好主意,就像i2
。 但是i3
和i4
不应该有相同的位模式,因此映射到相同的int
值?
符号扩展是使i2
和i3
负的原因。
在表达式(0 | b)
, b
被提升为int,并且作为此促销的一部分发生符号扩展。
在分配给i4
的表达式中没有发生这种情况。 常量1
和7
已经是整数,因此不涉及符号扩展。
在这一行:
i3 = 0 | b;
由于|,“b”变量自动提升为带有符号扩展名的int
类型 运算符,因此变为(int)-128
,即0xffffff80
。
当“或”ed为零时,它仍然是相同的值,即-128
不, i4
不是字节值,它是一个int
。 这意味着它的符号位是第31位,而不是第7位。
更新 : i3
也是一个int
,但它是通过扩展一个byte
来初始化的,所以它保持符号不受byte
值的影响。
i2 = (int) b;
i3 = 0 | b;
i3语句相当于:
i3 = 0 | ((int) b) = 0 | i2
i3 = 0 | ((int) b) = 0 | i2
很自然地它将具有与i2相同的值
这很简单。 i3 = 0 | b;
得到像byte
一样的评估,然后它被转换为int
。 而i4 = 1 << 7;
将值评估为int
并将其分配给int
。 所以在第一种情况下,我们从byte
获得10000000b
为int
,这将给出-128
。 在第二个我们只是将这个值赋给int
而不使用强制转换,这给了我们128
。
如果要在字节中获取位模式的无符号值:
b & 0xff
另见这个旧答案 。
在
i3 = 0 | b;
我猜0 | b part被评估为一个字节,然后将结果转换为int,而in
i4 = 1 << 7;
1 << 7部分已经是一个int。
以上猜测已经在评论中指出是错误的!
正确的版本是:在顶部表达式中,在OR操作之前,b已经转换为带符号扩展名的int。