swift - Swift 到 Kotlin 之谜
问题描述
我正在将一些 iOS 代码(Swift)转换为用于控制蓝牙设备(BLE)的 Android(Kotlin)。
我相信 Swift 和 Kotlin 以及 Unsigned Ints 等之间存在一些差异,但我似乎无法获得相同的输出。
iOS 代码:输出 13365
print ("IMPORTANT \(fourthData as NSData)") // Value is 0x3534
var fourth = Int32()
_ = Swift.withUnsafeMutableBytes(of: &fourth, { fourthData.copyBytes(to: $0) } )
print ("IMPORTANT \(fourth)") // 13365
Android 代码:输出为 13620
@ExperimentalUnsignedTypes // just to make it clear that the experimental unsigned types are used
fun ByteArray.toHexString() = asUByteArray().joinToString("") { it.toString(16).padStart(2, '0') }
Log.i("Decode", fourthData.toHexString()) // 3534
Log.i("Decode", "${fourthData.toHexString().toUInt(16)}") //13620
我尝试过 Int、UInt BigInteger 和 Long。我错过了什么
解决方案
正如评论者已经指出的那样,values13620
和13365
are0x3534
和 0x3435
分别。换句话说,值因字节顺序而异。
十进制的 32 位数字13620
等于0x00003534
十六进制,因此它将由四个字节表示00-00-35-34
。
但是,计算机通常不会按该顺序表示值。两种常用的表示是Big Endian和Little Endian。Big Endian 将按自然顺序表示字节,00-00-35-34
但 Little Endian 会将字节交换为00-00-34-35
.
Java (Kotlin) 总是对所有内容使用 Big Endian 表示。另一方面,如果你只是Int
在 Swift 中得到一个内存布局,你就会得到机器表示。机器表示通常是 Little Endian,但在架构之间可能会有所不同。当直接将数值重新解释为字节时,您应该始终小心,反之亦然。
在这种特定情况下,如果您确定Data
包含 Big Endian 整数,则可以使用Int32(bigEndian: fourth)
将值从 Big Endian 交换为机器表示。
推荐阅读
- c# - 将 DomainDbContext 与 IdentityDbContext 解耦
- python-3.x - Gurobi:在目标函数中添加对数项和指数项?
- python - 你如何在应用程序之间使用 ManyToManyFields 而不产生循环导入?
- html - 使用 Bootstrap 的产品示例并试图弄清楚我如何添加图像
- javascript - 是否可以使用 JavaScript 控制鼠标跟踪速度(光标移动多少以响应鼠标的运动)
- python - 如何在 Python 中将字符串的内容作为代码的一部分?
- python - 有没有办法让给定类的 HTML 分区必须是连续的?
- r - 通过 R 中的 system2() 对终端提示响应是
- postgresql - 将 MySQL 中的 SUBSTRING_INDEX() 转换为 PostgreSQL
- docker - 运行 docker exec 时如何获取 psql select 命令的输出?