Int到UInt(反之亦然)在Swift中进行位转换

Mic*_*ata 21 binary macos casting ios swift

我正在寻找一种直接的方法来将Int的位值转换为UInt,反之亦然.例如(为简单起见,使用8位整数)我想实现以下目的:

let unsigned: UInt8 = toUInt8(-1)  // unsigned is 255 or 0xff
let signed:   Int8  = toInt8(0xff) // signed is -1 
Run Code Online (Sandbox Code Playgroud)

起初我提出了以下解决方案:

let unsigned = unsafeBitCast(Int8(-1), UInt8.self)
let signed   = unsafeBitCast(UInt8(0xff), Int8.self)
Run Code Online (Sandbox Code Playgroud)

但Apple在"unsafeBitCast()"文档中声明如下:

..警告::打破Swift类型系统的保证; 小心使用.几乎总有一种更好的方法可以做任何事情.

有没有人有更好的方法?

rin*_*aro 38

你可以做:

let unsigned = UInt8(bitPattern: Int8(-1)) // -> 255
let signed   = Int8(bitPattern: UInt8(0xff)) // -> -1
Run Code Online (Sandbox Code Playgroud)

存在许多类似的初始化器:

extension Int8 {
    init(_ v: UInt8)
    init(_ v: UInt16)
    init(truncatingBitPattern: UInt16)
    init(_ v: Int16)
    init(truncatingBitPattern: Int16)
    init(_ v: UInt32)
    init(truncatingBitPattern: UInt32)
    init(_ v: Int32)
    init(truncatingBitPattern: Int32)
    init(_ v: UInt64)
    init(truncatingBitPattern: UInt64)
    init(_ v: Int64)
    init(truncatingBitPattern: Int64)
    init(_ v: UInt)
    init(truncatingBitPattern: UInt)
    init(_ v: Int)
    init(truncatingBitPattern: Int)
    init(bitPattern: UInt8)
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*ata 5

我走的是代数路线。测试一直很痛苦,因为强类型很容易导致执行中断,PlayGround 从 toUInt 函数返回一个负值,它不断崩溃或在执行双重转换时出现有趣的错误(我打开了一个错误报告)。无论如何,这就是我最终的结果:

func toUint(signed: Int) -> UInt {

    let unsigned = signed >= 0 ?
        UInt(signed) :
        UInt(signed  - Int.min) + UInt(Int.max) + 1

    return unsigned
}

func toInt(unsigned: UInt) -> Int {

    let signed = (unsigned <= UInt(Int.max)) ?
        Int(unsigned) :
        Int(unsigned - UInt(Int.max) - 1) + Int.min

    return signed
}
Run Code Online (Sandbox Code Playgroud)

我用所有极端值(UInt.min、UInt.max、Int.min、Int.max)对它们进行了测试,当 XCode 没有发疯时,它似乎可以工作,但看起来过于复杂。奇怪的是,可以使用 hashvalue 属性简单地实现 UInt 到 Int 位转换,如下所示:

signed = UInt.max.hashValue // signed is -1
Run Code Online (Sandbox Code Playgroud)

但显然它不能保证总是有效(它应该,但我宁愿不冒险)。

任何其他想法将不胜感激。