这个循环将无限期地继续:
char a = 100;
for(a=100; a>=0;--a)
System.out.println(a);
Run Code Online (Sandbox Code Playgroud)
是否会发生这种情况,因为a被提升为算术运算的int值,并从16位char值扩展到32位,因此将始终保持正值?
它确实会无限循环 - 你说的理由很接近.这是因为a
不能代表任何数量并不满足a >= 0
- char
是无符号.算术下溢在Java中是明确定义的,并且没有指示.请参阅规范的以下相关部分.
整数运算符不以任何方式指示上溢或下溢.
这意味着除了比较值之外没有溢出/下溢的迹象......例如,如果a
<= --a
,那么这意味着发生了下溢.
在减法之前,对值1和变量的值执行二进制数字提升(第5.6.2节).如有必要,通过缩小基元转换(第5.1.3节)和/或在存储之前对变量类型进行装箱转换(第5.1.7节)来缩小差异.前缀减量表达式的值是存储新值后变量的值.
因此,我们可以看到这里有两个主要步骤:二进制数字促销,然后是缩小的初始转换.
应用扩展基元转换(第5.1.2节)来转换由以下规则指定的一个或两个操作数:
- 如果任一操作数是类型
double
,则另一个操作数转换为double
.- 否则,如果任一操作数是类型
float
,则另一个操作数转换为float
.- 否则,如果任一操作数是类型
long
,则另一个操作数转换为long
.- 否则,两个操作数都将转换为类型
int
.
我们可以看到递减表达式a
被视为处理为int
,从而执行扩展转换.这允许它表示值-1.
缩小的原始转换可能丢失关于数值的总量值的信息,并且还可能失去精度和范围.
...
将有符号整数缩小到整数类型T只会丢弃除n个最低位之外的所有位,其中n是用于表示类型T的位数.除了可能丢失有关数值大小的信息之外,这可能导致结果值的符号与输入值的符号不同.
仅保留n个最低阶位意味着仅保留int
表达式的最低16位a - 1
.由于-1是0b11111111 11111111 11111111 11111111在这里,只有较低的0b11111111 11111111保存.由于char
是无符号的,所有这些位都对结果有贡献,给出65535.
注意到这里有什么?从本质上讲,这意味着Java整数算法是模块化的 ; 在这种情况下,模数是2 ^ 16或65536,因为char
它是16位数据类型.-1(mod 65536)≡65535,因此减量将回绕.
归档时间: |
|
查看次数: |
135 次 |
最近记录: |