我try 从0到255,无符号字节的范围,这是我的代码

for (b in UByte.MIN_VALUE..UByte.MAX_VALUE) {
    // do something with b
}

但为什么它从0扩展到2#32 -1(无符号int的范围)?

是否存在隐藏的自动类型转换?

我试图观察这个范围的大小,代码:

val range = UByte.MIN_VALUE..UByte.MAX_VALUE
println(range.toList().size)

它输出"256"

不符合收件箱代码

推荐答案

我想您刚刚发现了一个编译器错误!

通常,对于这样的for循环,编译器会生成从UIntRange获取iterator的代码,并执行while (iterator.hasNext())循环.

然而,看看生成的Java字节码(这种行为无法在Kotlin/JS上重现),编译器似乎试图将其优化为类似于以下Java(伪)代码的C风格for循环:

for (UInt b = UByte.MIN_VALUE ; b <= UByte.MAX_VALUE ; b++) {
    // ...
}

然而,它没有执行b <= UByte.MAX_VALUE,而是生成b <= UInt.MAX_VALUE.以下是字节码示例:

 5: iconst_0
 6: istore_1
 7: iload_1
 8: iconst_m1
 9: invokestatic  #18                 // Method kotlin/UnsignedKt.uintCompare:(II)I
12: ifgt          28
15: iload_1
16: istore_2
17: iload_2
18: iconst_m1
19: if_icmpeq     28
22: iinc          1, 1
25: goto          15
28: return

注意iconst_m1,这将-1推入为int(这是无符号int的最大值).


为了实现正确的结果,您可以首先将范围表达分配给某个本地val,因此编译器不会进行这种优化(尽管这在技术上无法保证).

这显然违反了Kotlin规范规定的for循环应该做的事情.根据specfor循环相当于:

when(val iter = (UByte.MIN_VALUE..UByte.MAX_VALUE).iterator()) {
    else -> while (iter.hasNext()) {
        val b = iter.next()
        // loop body goes here...
    }
}

但这只能从0到255循环,这是正确的.

Kotlin相关问答推荐

如果一项工作失败,请继续在Kotlin 等待其他工作/子元素完成

在 Kotlin 中实现并输入 Either

在 Kotlin 中,为什么我们要在闭包中捕获值

Lets plot Kotlin中的多轴比例

内容更改后的 var 重新计算

如何在 kotlin 中使用带有泛型的密封类

在 Kotlin 中,我可以在集合上有一个条件构建器元素吗?

kotlin 如何决定 lambda 中的参数名称?

如何在 Kotlin for Android 上使用setTextColor(hexaValue),

Kotlin JS JSON 反序列化

Kotlin:泛型、反射以及类型 T 和 T:Any 之间的区别

在粘贴时将 java 转换为 kotlin

Android 上的 Kotlin:将map到list

如何在Kotlin中创建无限长的序列

TypeConverter()在Android的TypeConverter错误中具有私有访问权限

(kotlin的Moshi)@Json vs@field:Json

使用导航组件在不同的图形之间导航

在 Kotlin 函数上使用 Mokito anyObject() 时,指定为非 null 的参数为 null

Android Kotlin .visibility

如何在 Gradle Kotlin DSL 中使用来自 gradle.properties 的插件版本?