Chapter 06

リテラル

文字列リテラル

ソースコード中に "Hello" のように書くと文字列リテラルになるのでした.では, " という文字そのものを出力したいときはどうすれば良いでしょうか? """ と書くと,残念ながら文字列の始まりと終わりが分からなくなってしまいます.そこで,エスケープというものが用意されています.

fn main() {
    println!("\"Fool,\" said I, \"you do not know\"");
}

文字列リテラル中に\"が登場すると,これは文字列の終わりではなく"という文字として扱われます.すなわち上のコードを実行すると "Fool," said I, "you do not know" と出力されます.

\ という文字自体は, \\ と表されます.

fn main() {
    println!("/\\
\\/");
}

実行すると

/\
\/

となります.

この他に,これらのエスケープが存在します.

生文字列リテラル

文字列がエスケープだらけになると,見にくくて何がなんだかわからなくなってしまいます.そこで生文字列リテラルというものも用意されています.

fn main() {
    println!(r"\\\\\\\\\\");
}

r" " で囲われた部分が生文字列リテラルです.バックスラッシュ \ がエスケープのための文字として扱われることはなく,出力はそのまま \\\\\\\\\\ になります.

生文字列リテラルを用いて " を出力するときには, r" " の代わりに r#" "# で囲います.

fn main() {
    println!(r#""Fool," said I, "you do not know""#);
}

"# が来るまで文字列は終わりません.出力は "Fool," said I, "you do not know" となります.

生文字列リテラルで "# を出力したいときは, # の数を増やして r##" "## で囲います. # の数はいくらでも増やせます.

整数リテラル

整数を表す型には, i32 の他に i64 というものも存在します. i64 は 64 ビットを使って i32 よりはるかに広い範囲の値を表現することができます.

1020 などの整数リテラルも,変数と同様に型をもちます.

整数リテラルの型は,まず周囲の情報から推論されます.

fn main() {
    let big_number: i64;
    big_number = 2147483648;
    println!("{}", big_number);
}

変数 big_numberi64 型で,そこに 2147483648 を代入しようとしているので, 2147483648 も同じ i64 型でなければなりません.よって 2147483648i64 型の整数リテラルになります.

次のコードはエラーになります.

fn main() {
    let big_number: i32;
    big_number = 2147483648;
    println!("{}", big_number);
}

今度は big_numberi32 型なので,整数リテラル 2147483648i32 型ということになります.しかし, i32 型は -2^{31} 以上 2^{31} 未満の数しか扱えないので,整数リテラル 2147483648i32 型の値にすることはできません.エラーメッセージは次のようになります.

error: literal out of range for `i32`
 --> src/main.rs:3:18
  |
3 |     big_number = 2147483648;
  |                  ^^^^^^^^^^
  |
  = note: `#[deny(overflowing_literals)]` on by default
  = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647`

literal out of range for `i32` は「リテラルが i32 で表せる範囲を超えている」という意味です. the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647` は「i32 で表せる範囲は -2147483648 以上 2147483647 以下であり,リテラル 2147483648i32 の値にすることはできない」という意味です.

型を推論するための材料が無かった場合,整数リテラルは自動的に i32 として扱われます.よって次のコードも同じエラーになります.

fn main() {
    let big_number;
    big_number = 2147483648;
    println!("{}", big_number);
}

big_number の型注釈を取り去ったので, 2147483648 の型を推論する材料がありません.よって 2147483648 は自動的に i32 型になりますが,値 2147483648 は i32 型で表せません.

最後に型の名前を付けて 2147483648i64 あるいは 2147483648_i64 とすると,その整数リテラルは強制的に i64 型になります.よって次のコードは正常に動きます.

fn main() {
    let big_number;
    big_number = 2147483648_i64;
    println!("{}", big_number);
}

変数 big_number の型については, i64 型の値 2147483648_i64 を代入していることから, i64 であると推論されます.

競技プログラミングでは,しばしば i32 ではなく i64 を使わなければいけないような問題が出てきます.

アンダースコア _ は,整数リテラルの好きな場所(先頭を除く)に好きなだけ挿入できます.たとえば 1_____2__3___123 と同じです.これは,桁数の多い数を扱うときに 3 桁ごとに挿入して 1_000_000_007 のように見やすくするために使われます.

浮動小数点数リテラル

浮動小数点数を表す型には 64 ビットの f64 と 32 ビットの f32 があります. 2.510. のような浮動小数点数リテラルは,型推論の材料がないとき自動的に f64 として扱われます.

10 は整数リテラルですが, 10. は浮動小数点数リテラルであることに注意してください.

0.10 を省略して .1 と書くことはできません.

また,浮動小数点数リテラルでは指数表記を使うことができます.

fn main() {
    let avogadro_constant;
    avogadro_constant = 6.02e+23;
    println!("{}", avogadro_constant);
}

6.02e23 あるいは 6.02e+23 と書くと, 6.02 \times 10^{23} という意味になります.一方たとえば 1.6e-19 と書くと 1.6 \times 10^{-19} になります.

浮動小数点数リテラルについても,最後に f64f32 を付けて型を指定することができます.

fn main() {
    let pi = 3.14_f32;
}

ただし, 10. のように最後が . で終わる場合は 10.f6410._f64 などと書くことができません.このようなときは,小数点 . を書かずに f64f32 を付けます.

fn main() {
    let fuji = 3776_f64;
}

最後に f64f32 が付いている場合は,小数点 . が無くても整数リテラルにはならず,浮動小数点数リテラルとして扱われます.