3

这个循环将无限期地继续:

char a = 100;
for(a=100; a>=0;--a)
    System.out.println(a);

是否会发生这种情况,因为 a 被提升为算术运算的 int 值并从 16 位 char 值扩大到 32 位,因此将始终保持正数?

4

3 回答 3

8

它确实会无限循环——你所说的原因很接近。发生这种情况是因为a不能表示任何不满足的数字-a >= 0char符号的。算术下溢在 Java 中定义明确且未指明。请参阅规范的以下相关部分。

  • §4.2.2

    整数运算符不以任何方式指示上溢或下溢。

    这意味着除了比较值之外没有溢出/下溢的迹象......例如,如果a<= --a,那么这意味着发生了下溢。

  • §15.15.2

    在减法之前,对值 1 和变量的值执行二进制数字提升(第 5.6.2 节)。如有必要,通过缩小原始转换(第 5.1.3 节)和/或在存储变量之前对其类型进行装箱转换(第 5.1.7 节)来缩小差异。前缀递减表达式的值是存储新值后变量的值。

    因此,我们可以看到这里有两个主要步骤:二进制数字提升,然后是缩小原始转换。

  • §5.6.2

    加宽原语转换(第 5.1.2 节)适用于转换以下规则指定的一个或两个操作数:

    • 如果任一操作数的类型为double,则将另一个转换为double
    • 否则,如果任一操作数的类型为float,则将另一个转换为float
    • 否则,如果任一操作数的类型为long,则将另一个转换为long
    • 否则,两个操作数都转换为 type int

    我们可以看到递减表达式与a视为一起工作int,因此执行了扩大转换。这允许它表示值-1

  • §5.1.3

    缩小原语转换可能会丢失有关数值整体大小的信息,也可能会丢失精度和范围。

    ...

    有符号整数到整数类型 T 的窄化转换只会丢弃除n 个最低位之外的所有位,其中n是用于表示类型 T 的位数。此外,可能会丢失有关数值大小的信息,这可能会导致结果值的符号与输入值的符号不同。

    仅保留n 个最低位意味着仅保留int表达式的最低 16 位a - 1。由于-1这里是0b11111111 11111111 11111111 11111111,所以只保存低位的0b11111111 11111111。由于char是无符号的,所有这些位都对结果有贡献,给出65535

注意到这里的东西了吗?本质上,这一切都意味着 Java 整数运算是模块化的;在这种情况下,模数是2^1665536,因为char它是 16 位数据类型。-1 (mod 65536) ≡ 65535,所以减量会回绕。

于 2012-09-09T06:01:58.100 回答
4

没有。char值是无符号的 - 当它们低于 0 时,它们会回到 65535 左右。

交换- 然后它会工作charbyte

于 2012-09-09T06:01:35.660 回答
1

正如其他人所说,charJava 中的类型是无符号的,所以a >= 0总是如此。当a达到 0 然后再次递减时,它变为 65535。如果你只是想反常,你可以这样编写循环以在 101 次迭代后终止:

char a = 100;
for(a=100; a<=100;--a)
    System.out.println(a);

然后,代码审查员可能会因为写出如此可怕的东西而让你心碎。:)

于 2012-09-09T06:25:44.150 回答