如何在 Swift 中使用位操作?

How to work with bit operations in Swift?

我需要形成一个 20 字节的数据包,并通过蓝牙将有效负载发送到硬件外围设备。

这个20字节的数据包内部分为14组数据,每组11位,最后6位为空字符。

因此,总计: 160 位(20 字节)= 14(组)* 11(位)+ 6(空字符)

11位又分为2位、3位、6位各3组。然而,这对主要问题并不重要,我目前可以通过 'Int16' 来形成 11 位。过滤11位我会做移位操作,我知道。

如果我只有一个数据集,那么我应该用空字符填充除前11位之外的所有20个字节,如果是两个数据集,那么除了22位之外的所有字节都应该是空字符。

我面临的问题是形成这个连续的 160 位,因为奇数位是 11。我想采用 'Int' 并进行移位(<<)操作,然后进行按位或( |) 但 Int 是 64 位。

目前我认为采用 20 个固定大小的字符数组适合这种情况。虽然在概念上我认为这是最好的方法,但在编程上我无法形成具有实现这一目标的所有条件的逻辑。我想我需要把所有的逻辑放在一个循环中。

任何人都可以告诉我这是实现此目标的正确方法吗,并指导我解决它,如果这是最好的方法。或者指出任何其他可用的方式。

您不需要在最后将所有数据集打包到 20 字节的数组中,因此将它们保存在长度为 14 的 Int 数组中。使用这种方式更容易。当您需要将其发送到硬件时,将其转换为长度为 20 的 UInt8 数组:

struct DataPacket {
    var dataSets = [Int](count: 14, repeatedValue: 0)

    func toCArray() -> [UInt8] {
        var result = [UInt8](count: 20, repeatedValue: 0)
        var index = 0
        var bitsRemaining = 8
        var offset = 0

        for value in self.dataSets {
            offset = 10

            while offset >= 0 {
                let mask = 1 << offset
                let bit = ((value & mask) >> offset) << (bitsRemaining - 1)
                result[index] |= UInt8(bit)

                offset -= 1
                bitsRemaining -= 1
                if bitsRemaining == 0 {
                    index += 1
                    bitsRemaining = 8
                }
            }
        }

        return result
    }
}

// Usage:
var packet = DataPacket()
packet.dataSets[0] = 0b11111111111
packet.dataSets[1] = 0b00000000011
// etc...

let arr = packet.toCArray()

有很多移位操作正在进行,所以我无法解释所有这些操作。一般的理想是将每个 11 位数据集分配到字节中,并根据需要溢出到下一个字节。

Code Different 提出的解决方案的变体:

struct DataPacket {
    var dataSets = [Int16](count: 14, repeatedValue: 0)

    func getPacket() -> [UInt8] {
        var packet = [UInt8](count: 20, repeatedValue: 0)
        var idxPacket = 0

        for dataSet in dataSets {
            for idxBit in 1...11 {
                if dataSet & 1 << (11 - idxBit) != 0 {
                    packet[idxPacket / 8] |= UInt8(0b1000_0000 >> (idxPacket % 8))
                }
                idxPacket += 1
            }
        }

        return packet
    }
}