## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# 型キャスト

Rustは基本データ型について暗黙的な型変換（`coerction`）を行うことはありません。しかし明示的な型変換（`casting`）は可能です。その場合`as`キーワードを使用します。

整数型から整数型へ型変換する場合、C言語で可能なケースの場合はC言語と同じです。C言語で未定義の場合の挙動も、Rustでは完全に定義されています。

    // オーバーフローを起こすようなキャストによる警告を無視します。
    #![allow(overflowing_literals)]

    fn main() {
        let decimal = 65.4321_f32;

        // エラー！暗黙的な型変換はできません。
        let integer: u8 = decimal;
        // FIXME ^ この行をコメントアウトしましょう

        // 明示的な型変換
        let integer = decimal as u8;
        let character = integer as char;

        // エラー！変換ルールには制限があります。
        // 浮動小数点数を文字に直接変換することはできません。
        let character = decimal as char;
        // FIXME ^ この行をコメントアウトしましょう

        println!("Casting: {} -> {} -> {}", decimal, integer, character);

        // 何らかの値を符号なしの型（仮にTとする）へキャストすると
        // 値がTに収まるまで、T::MAX + 1 が加算あるいは減算されます。

        // 1000はすでにu16に収まっているため変化しません。
        println!("1000 as a u16 is: {}", 1000 as u16);

        // 1000 - 256 - 256 - 256 = 232
        // 詳しく見てみると、最下位ビットから8bitが保持され、
        // 残りの上位ビットが切り取られる形になります。
        println!("1000 as a u8 is : {}", 1000 as u8);
        // -1 + 256 = 255
        println!("  -1 as a u8 is : {}", (-1i8) as u8);

        // 正の数では、これは剰余と同じです。
        println!("1000 mod 256 is : {}", 1000 % 256);

        // 符号付きの型にキャストする場合、（ビットとして見た）結果は対応する
        // 符号無し型へのキャストを行った結果と同じです。
        // 最上位ビットが1であれば、その値は負であることを示しています。

        // すでに収まっている場合はそのままです。
        println!(" 128 as a i16 is: {}", 128 as i16);

        // 境界値のケースを考えると、128の8ビットにおける2の補数は -128です。
        println!(" 128 as a i8 is : {}", 128 as i8);

        // 上で示した例を繰り返すと
        // 1000 as u8 -> 232
        println!("1000 as a u8 is : {}", 1000 as u8);
        // 232の8ビットにおける補数は -24。
        println!(" 232 as a i8 is : {}", 232 as i8);

        // Rust 1.45以降、浮動小数点数を整数にキャストするとき、
        // `as`キーワードが *飽和的キャスト* を行います。
        // 浮動小数点数の値が上限を超えたり下限を下回ったりする場合は、
        // 戻り値は越えられた境界の値となります。

        // 300.0 as u8 は 255
        println!(" 300.0 as u8 is : {}", 300.0_f32 as u8);
        // -100.0 as u8 は 0
        println!("-100.0 as u8 is : {}", -100.0_f32 as u8);
        // nan as u8 は 0
        println!("   nan as u8 is : {}", f32::NAN as u8);

        // この挙動は実行時にややコストがかかるため、安全でない方法で回避できます。
        // ただし、結果はオーバーフローしたり *不正確な値* を返す場合があります。
        // この方法は賢く使いましょう。
        unsafe {
            // 300.0 as u8 は 44
            println!(" 300.0 as u8 is : {}", 300.0_f32.to_int_unchecked::<u8>());
            // -100.0 as u8 は 156
            println!("-100.0 as u8 is : {}", (-100.0_f32).to_int_unchecked::<u8>());
            // nan as u8 は 0
            println!("   nan as u8 is : {}", f32::NAN.to_int_unchecked::<u8>());
        }
    }