Swiftでビットパターンを維持した状態で整数型を変換するには、次のイニシャライザを使用します。
init<T>(truncatingIfNeeded source: T) where T : BinaryInteger
これを使って、符号無し整数と符号有り整数との間で変換できます。例えば、UInt8
で0x00
, 0x7F
, 0x80
, 0xFF
は10進数では次のようになります。
16進数 | UInt8での10進数 |
---|---|
0x00 | 0 |
0x7F | 127 |
0x80 | 128 |
0xFF | 255 |
同じ値がInt8
では次のようになります。
16進数 | Int8での10進数 |
---|---|
0x00 | 0 |
0x7F | 127 |
0x80 | -128 |
0xFF | -1 |
Playgroundで次のように入力して実行すると、期待した変換ができることが確認できます。
let u1 = UInt8(0x00)
let u2 = UInt8(0x7F)
let u3 = UInt8(0x80)
let u4 = UInt8(0xFF)
let i1 = Int8(truncatingIfNeeded: u1)
let i2 = Int8(truncatingIfNeeded: u2)
let i3 = Int8(truncatingIfNeeded: u3)
let i4 = Int8(truncatingIfNeeded: u4)
引数のラベルを指定しないと次のイニシャライザが使われます。
init<T>(_ source: T) where T : BinaryInteger
このイニシャライザでも変換できますが、範囲外の値のときにエラーになります。具体的には、UInt8
からInt8
への変換では、128
以上の値でエラーとなります。
次のコードをPlaygroundで実行してください。
let u1 = UInt8(0x00)
let u2 = UInt8(0x7F)
let u3 = UInt8(0x80)
let u4 = UInt8(0xFF)
let i1 = Int8(u1)
let i2 = Int8(u2)
let i3 = Int8(u3)
let i4 = Int8(u4)
すると、次のようにコンソールに出力され、u3
からInt8
を作るときにエラーになります。
Swift/Integers.swift:3564: Fatal error: Not enough bits to represent the passed value
init(truncatingIfNeeded:)
は数値のビットパターンを維持したままタイプを変換するので成功します。UInt8
の128
とInt8
の-128
はどちらも2進数では10000000
です。
init(_ source:)
は数値を解釈するので範囲外となってしまいます。Int8
の取り得る値は-128
以上127
以下です。u3
は128
なので範囲外となります。