如何在Swift中将整数(Int)转换为4字节的字节数组?

10
我正在使用Swift,并尝试将一个整数(例如:-1333)转换为4个字节的字节数组。我已经成功将一个Int转换为8个字节的数组(-1333变成[255, 255, 255, 255, 255, 255, 250, 203]),但我需要它变成4个字节。我知道其他语言如Java有实现这个功能的方法,但在Swift中是否也有类似的方式呢?以下是我的代码:(我参考了这个答案
func createByteArray(originalValue: Int)->[UInt8]{
        var result:[UInt8]=Array()

            var _number:Int = originalValue

            let mask_8Bit=0xFF

            var c=0
            var size: Int = MemoryLayout.size(ofValue: originalValue)
            for i in (0..<size).reversed(){
                //at: 0 -> insert at the beginning of the array
                result.insert(UInt8( _number&mask_8Bit),at:0)
                _number >>= 8 //shift 8 times from left to right
            }

        return result
    }
3个回答

27
在Java中,整数始终为32位,但在Swift中,它可以是32位或64位,具体取决于平台。您的代码创建了一个字节数组,其大小与Int类型相同,在64位平台上为8个字节。
如果您想将转换限制为32位整数,请改用Int32而不是Int,结果将是一个4字节的数组,与平台无关。
另一种替代转换方法是:
let value: Int32 = -1333
let array = withUnsafeBytes(of: value.bigEndian, Array.init)
print(array) // [255, 255, 250, 203]

或者作为适用于所有大小的整数类型的通用函数:

func byteArray<T>(from value: T) -> [UInt8] where T: FixedWidthInteger {
    withUnsafeBytes(of: value.bigEndian, Array.init)
}

例子:

print(byteArray(from: -1333))        // [255, 255, 255, 255, 255, 255, 250, 203]
print(byteArray(from: Int32(-1333))) // [255, 255, 250, 203]
print(byteArray(from: Int16(-1333))) // [250, 203]

0

然而,与Java使用大端不同,iOS平台使用'小端'

因此,如果它是

let value: Int32 = -1333
let array2 = withUnsafeBytes(of: value.littleEndian, Array.init)// [203, 250, 255, 255]

您可以通过以下扩展将值包装到数据中并检查字节来验证它。
extension FixedWidthInteger {
    var data: Data {
        let data = withUnsafeBytes(of: self) { Data($0) }
        return data
    }
}
value.data

提醒一下那些正在研究内存布局的iOS开发者。


0

对于初学者来说,很难理解上面答案中发生了什么。

public extension FixedWidthInteger {
    var bytes: [UInt8] {
        withUnsafeBytes(of: bigEndian, Array.init)
    }
}

首先,让我们更详细地重写计算属性bytes
var bytes: [UInt8] {
    var copyOfSelf = self.bigEndian // this defines the order of bytes in result array
    // for int '1' it can be [0, 0, 0, 0, 0, 0, 0, 1] 
    // or [1, 0, 0, 0, 0, 0, 0, 0] 
    return withUnsafeBytes(of: copyOfSelf) { urbp: UnsafeRawBufferPointer in
        // Array has a constructor 
        // init<S>(_ s: S) where Element == S.Element, S : Sequence
        // so 'UnsafeRawBufferPointer' confirms 'Sequence' protocol
        // and 'urbp' can be passed as a parameter to Array constructor
        return Array(urbp) 
    }
}

这里有一些测试来解释结果

final class FixedWidthIntegerTests: XCTestCase {
    func testBytes() {
        XCTAssertEqual([0,0,0,0,0,0,0,1], Int(1).bytes)
        XCTAssertEqual([255,255,255,255,255,255,255,255], UInt.max.bytes)
        XCTAssertEqual([127,255,255,255,255,255,255,255], Int.max.bytes)
        XCTAssertEqual([1], Int8(1).bytes)
        XCTAssertEqual([0,1], Int16(1).bytes)
        XCTAssertEqual([0,0,0,1], Int32(1).bytes)
    }
}

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