最大Java空头(32767)加1不转负?

Largest Java Short (32767) plus 1 not turning negative?

最近学习了二元制中表示正整数和负整数的补码法。然后,我尝试使用 java 和以下短代码来查看实际效果:

int a=2147483647;
System.out.println("a: "+a);
System.out.println("a+1: "+(a+1));
short b=32767;
System.out.println("b: "+b);
System.out.println("b+1: "+(b+1));

输出:

a: 2147483647

a+1: -2147483648

b: 32767

b+1: 32768

这让我很困惑,因为我认为 b+1,用二进制表示为 011111111111111,会变成 1000000000000000,或者用十进制表示 -32768。怎么回事?

虽然 b 是一个短整型,但表达式 (b + 1) 是一个整型。右操作数为int,左操作数提升为int,表达式为操作数提升后的类型。

来自 Java 语言规范,5.6.2. Binary Numeric Promotion

Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

  • If either operand is of type double, the other is converted to double.
  • Otherwise, if either operand is of type float, the other is converted to float.
  • Otherwise, if either operand is of type long, the other is converted to long.
  • Otherwise, both operands are converted to type int.

请注意,即使 两个 操作数都是短类型,也会发生最后一次提升。您无法避免使用 (b + (short) 1).

提升为 int

来自15.18.2. Additive Operators (+ and -) for Numeric Types

The type of an additive expression on numeric operands is the promoted type of its operands.

执行 + 会自动将 short 提升为 int。这样做你就会看到溢出。

System.out.println("b+1: "+(short)(b+1)); //-32768

来自 Java 语言规范,5.6.2. Binary Numeric Promotion

Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

  • If either operand is of type double, the other is converted to double.
  • Otherwise, if either operand is of type float, the other is converted to float.
  • Otherwise, if either operand is of type long, the other is converted to long.
  • Otherwise, both operands are converted to type int.

注意最后一条规则,本质上这意味着即使它们都是short,它们也会被提升为int,这是无法避免的。

你可以:

short b= 32767;
short d= 12;
System.out.println("b+1: "+ (d+b)); // 32779

答案仍然有效。

1 是一个 int 文字。当您计算 b+1 时,您实际上将 b 提升为 int,然后添加 1,结果是 32768,这是完全合法的 [=12] =] 值。如果您再次将其转换为 short,您将看到预期的溢出 (-32768):

System.out.println("b+1: " + (short)(b + 1));

正如其他人所指出的,加法将操作数提升为 int

请注意,+= 运算符会自动转换回 short:

short b=32767;
System.out.println(b + 1);  // 32768, because of integer promotion.

b += 1;                     // Equivalent to b = (short)(b + 1);
System.out.println(b);      // -32768

b++;/++b; 会产生与 b += 1.

相同的结果

无需混淆,试试这个:

short b = 32767;
short c = b + 1;

你得到了什么?对,你得到:

error: incompatible types: possible lossy conversion from int to short short c = b + 1;

那么,你的生产线上发生了什么? System.out.println("b+1: "+(b+1));?

好吧,b+1 对于 short 来说太大了,正如您所说的正确,但是在这里您向它添加了一个 int,使结果也成为一个 int。 32768 是一个有效的整数。

正如其他人已经指出的那样,如果您明确地将其转换为 (short),您就会得到您所要求的。

另一方面,这不适用于 short c = b + 1;,因为这里声明的类型是短整型,而实际类型是 int.

short c = (short) (b + 1); 解决了 "problem"