如何在Swift中将Int16转换为两个UInt8字节

15

我有一些二进制数据,将一个两个字节的值编码为带符号整数。

bytes[1] = 255  // 0xFF
bytes[2] = 251  // 0xF1

解码

这相当简单 - 我可以使用以下代码从这些字节中提取一个Int16值:

Int16(bytes[1]) << 8 | Int16(bytes[2])

编码

这是我遇到问题的地方。我的数据规范大多要求使用UInt,这很容易做到,但我在提取组成Int16的两个字节时遇到了麻烦。

let nv : Int16 = -15
UInt8(nv >> 8) // fail
UInt8(nv)      // fail

问题

我该如何提取组成一个 Int16 值的两个字节?


无符号转有符号可以实现,但可能会溢出。有符号转无符号可能会导致无意义的结果,因此它会阻止你。你想从中得到什么?-15 无法在无符号中表示。 - tadman
我正在尝试获取表示-15的字节,以便将它们存储回数组中。 - Jeef
4个回答

26

你应该使用无符号整数:

let bytes: [UInt8] = [255, 251]
let uInt16Value = UInt16(bytes[0]) << 8 | UInt16(bytes[1])
let uInt8Value0 = uInt16Value >> 8
let uInt8Value1 = UInt8(uInt16Value & 0x00ff)

如果您想将UInt16转换为位等效的Int16,则可以使用特定的初始化器进行转换:

let int16Value: Int16 = -15
let uInt16Value = UInt16(bitPattern: int16Value)

反之亦然:

let uInt16Value: UInt16 = 65000
let int16Value = Int16(bitPattern: uInt16Value)

对于您的情况:

let nv: Int16 = -15
let uNv = UInt16(bitPattern: nv)

UInt8(uNv >> 8)
UInt8(uNv & 0x00ff)

我的数据规范要求我将这两个字节解码为有符号整数,解码已经正常工作。 - Jeef
1
回答已更新。您应该先将 Int16 值转换为 UInt16,然后将其拆分成两个 UInt8 值。 - mixel

7
你可以使用 init(truncatingBitPattern: Int16) 初始化器:
let nv: Int16 = -15
UInt8(truncatingBitPattern: nv >> 8) // -> 255
UInt8(truncatingBitPattern: nv) // -> 241

3
Swift 4 中的翻译:UInt8(truncatingIfNeeded: nv) - Daniele Ceglia

3
我会这样做:
let a = UInt8(nv >> 8 & 0x00ff)  // 255
let b = UInt8(nv & 0x00ff)       // 241

0
extension Int16 {
    var twoBytes : [UInt8] {
        let unsignedSelf = UInt16(bitPattern: self)
        return [UInt8(truncatingIfNeeded: unsignedSelf >> 8),
                UInt8(truncatingIfNeeded: unsignedSelf)]
    }
}

var test : Int16 = -15
test.twoBytes // [255, 241]

1
请查看如何撰写答案。 添加更多细节来证明你的答案。 - Morse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接