diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 6d03c91..ccf7fc6 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -73,7 +73,7 @@ - [Raw lifetimes](rust-2021/raw-lifetimes.md) - [警告からエラーへの格上げ](rust-2021/warnings-promoted-to-error.md) - [マクロ規則における OR パターン](rust-2021/or-patterns-macro-rules.md) - - [C-string literals](rust-2021/c-string-literals.md) + - [C 文字列リテラル](rust-2021/c-string-literals.md) ## Rust 2024 diff --git a/src/rust-2021/c-string-literals.md b/src/rust-2021/c-string-literals.md index bda15a2..d2c2e49 100644 --- a/src/rust-2021/c-string-literals.md +++ b/src/rust-2021/c-string-literals.md @@ -1,33 +1,63 @@ -> **Rust Edition Guide は現在 Rust 2024 のアップデート作業に向けて翻訳作業中です。本ページはある時点での英語版をコピーしていますが、一部のリンクが動作しない場合や、最新情報が更新されていない場合があります。問題が発生した場合は、[原文(英語版)](https://doc.rust-lang.org/nightly/edition-guide/introduction.html)をご参照ください。** - + + +# C 文字列リテラル + + +## 概要 + +リテラル `c"foo"` や `cr"foo"` で、[`&core::ffi::CStr`][CStr] 型の文字列を表現できます。 + +[CStr]: https://doc.rust-lang.org/core/ffi/struct.CStr.html + + + +## 詳細 + + +Rust 1.77 から、`c` や `cr` から始まる C 文字列リテラル構文を用いて C 文字列を表現できるようになりました。 + + +以前は、C 言語の API と相互運用できるようにヌルバイトで終端された文字列リテラルを正しく作成することは困難でした。 +それまでは [`cstr`] クレートが広く使われていましたが、重い処理である proc macro のコンパイルが必要でした。 +今回導入されたリテラル構文により、暗黙にヌルバイトで終端された [`&core::ffi::CStr`][CStr] 型の C 文字を直接記述できるようになりました。 ```rust,edition2021 # use core::ffi::CStr; assert_eq!(c"hello", CStr::from_bytes_with_nul(b"hello\0").unwrap()); +// ↓ 訳: バイトエスケープ \xff も使えます assert_eq!( c"byte escapes \xff work", CStr::from_bytes_with_nul(b"byte escapes \xff work\0").unwrap() ); +// ↓ 訳: ユニコードエスケープ \u{00E6} も使えます assert_eq!( c"unicode escapes \u{00E6} work", CStr::from_bytes_with_nul(b"unicode escapes \xc3\xa6 work\0").unwrap() ); +// ↓ 訳: ユニコード文字 αβγ は UTF-8 で表現されます assert_eq!( c"unicode characters αβγ encoded as UTF-8", CStr::from_bytes_with_nul( @@ -35,6 +65,7 @@ assert_eq!( ) .unwrap() ); +// ↓ 訳: 文字列は複数行にわたることができます assert_eq!( c"strings can continue \ on multiple lines", @@ -42,13 +73,25 @@ assert_eq!( ); ``` + + +C 文字列は内部にヌル文字(エスケープ `\0` など)を含めることはでいません。 + + +C 文字列では通常の文字列と同様、`cr` で「生」構文を使うこともできます。 +生 C 文字列はバックスラッシュ `\` によるエスケープが効かないので、バックスラッシュを含む文字列を書きたいときに有効です。 +`#` で囲むことで、二重引用符 `"` も含めることもできます。 +`#` を複数使えば、`"#` が内部に含まれる文字列も表現可能です。 + +```rust,edition2021 +assert_eq!(cr"foo", c"foo"); +// 記号 # を使えば、 " を含められます。 +assert_eq!(cr#""foo""#, c"\"foo\""); +// この文字列の場合、 # が2つ必要です。 +assert_eq!(cr##""foo"#"##, c"\"foo\"#"); +// エスケープは無効です。 +assert_eq!(cr"C:\foo", c"C:\\foo"); +``` + + + +詳しくは[言語リファレンス]を参照してください。 + +[`cstr`]: https://crates.io/crates/cstr +[言語リファレンス]: https://doc.rust-lang.org/reference/tokens.html#c-string-and-raw-c-string-literals + + + +## 移行 + + +移行が必要なケースはまれで、`c"…"` や `cr"…"` のようなトークン列を含むマクロ呼び出しだけ変更の必要があります。 +2021 エディションより前ではこれらは2トークンに分割されましたが、2021 では単一トークンと解釈されるからです。 + +2021 エディションで[構文が予約]されるにあたり、問題となりうるマクロ呼び出しは、移行リント`rust_2021_prefixes_incompatible_syntax` で警告が出るようになっています。 +詳しくは当該の節を参照してください。 + + + +[構文が予約]: reserved-syntax.md