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。