2012-09-09 88 views
3

这个循环会一直继续下去:为什么使用char循环,因为它的索引循环是无限的?

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

它是否会发生,因为一个被推举为算术运算int值和被扩大至从16位字符值32位,因此将始终保持积极的态度?

+5

你试过吗? – oldrinb

+0

@oldrinb - 只回答“将它”。更有趣的问题是“为什么”。 –

+0

@StephenC我的评论回答了标题中的问题。 “为什么”我在下面回答。 – oldrinb

回答

8

它确实会无限循环 - 你说的原因很接近。发生这种情况是因为a不能代表没有的任何数字满足a >= 0 - char是无符号的。算术下溢在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
    • 否则,两个操作数都转换为int类型。

    我们可以看到,减量表达可与aint处理,由此进行扩大转换。这允许它代表值-1

  • §5.1.3

    甲基本收缩转换可能会失去约数值的总幅度的信息,并且还可能会丢失精度和范围。

    ...

    带符号的整数的收缩转换为整数类型T简单地丢弃所有,但Ñ最低阶位,其中Ñ是用于表示类型T.比特数除了可能丢失有关数值大小的信息之外,这可能会导致结果值的符号与输入值的符号不同。

    仅保留Ñ最低阶位意味着只有int表达a - 1的最低16位被保留。由于-10b11111111 11111111 11111111 11111111此处仅保存下一个0b11111111 11111111。由于char是无符号的,因此的所有都贡献了结果,给出。

在这里注意什么?实质上,这意味着Java整数运算是模块化;在这种情况下,模数是2^16或,因为char是16位数据类型。 -1(mod 65536)≡65535,所以减量将回绕。

+0

这真的是算术下溢?比照http://en.wikipedia.org/wiki/Arithmetic_underflow – jsj

+0

@ trideceth12你是对的,我措辞不正确:-p – oldrinb

+1

你仍然有这个错误。整数下溢确实发生在Java中。它只是没有**表示** ......正如你所引用的JLS文本所述。也就是说,不会抛出异常,并且没有任何东西可以直接检测是否发生了下溢。 –

4

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

交换charbyte - 然后它会工作。

+2

Ermmm ...你的意思是65535. –

+0

Stephen,你是对的。我假设它像C的字符。 –

+1

@NickODell那么你应该知道* plain *'char'的签名是实现定义的......它只能保证能够适合整个ASCII字符集(0-127),并且C99确保它可以存储在至少8位。 – oldrinb

1

正如其他人所说,Java中的char类型是无符号的,因此a >= 0将始终为真。当a命中0,然后递减一次,就变成65535如果你只是想乖张,你可以写你的循环后,101次迭代终止这样:然后

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

代码审阅者可以有一个字段因为写这样一件可怕的事情而把你分开。 :)