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

时间:2014-11-25 12:44:58

标签: ios macos swift casting binary

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

let unsigned: UInt8 = toUInt8(-1)  // unsigned is 255 or 0xff
let signed:   Int8  = toInt8(0xff) // signed is -1 

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

let unsigned = unsafeBitCast(Int8(-1), UInt8.self)
let signed   = unsafeBitCast(UInt8(0xff), Int8.self)

但Apple在“unsafeBitCast()”文档中说明了以下内容:

  

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

有没有人有更好的方法?

3 个答案:

答案 0 :(得分:36)

你可以这样做:

let unsigned = UInt8(bitPattern: Int8(-1)) // -> 255
let signed   = Int8(bitPattern: UInt8(0xff)) // -> -1

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

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)
}

答案 1 :(得分:3)

我采用了代数路线。测试一直很痛苦,因为强大的打字很容易导致执行溢出,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
}

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

signed = UInt.max.hashValue // signed is -1

但显然不能保证始终有效(应该,但我宁愿不抓住机会)。

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

答案 2 :(得分:0)

numericCast(...)是您正在寻找的。它是一组通用函数,可以转换为不同的数字类型。它根据参数类型和返回类型选择正确的实现。