From 81fbb7ce65997a5490736c339e8feb655ef5ca3c Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Fri, 31 Jan 2025 12:56:15 +0900 Subject: [PATCH] =?UTF-8?q?[2021]=20=E3=80=8CC=E6=96=87=E5=AD=97=E5=88=97?= =?UTF-8?q?=E3=83=AA=E3=83=86=E3=83=A9=E3=83=AB=E3=80=8D=E3=82=92=E7=BF=BB?= =?UTF-8?q?=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SUMMARY.md | 2 +- src/rust-2021/c-string-literals.md | 155 +++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 src/rust-2021/c-string-literals.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index ab10822..d2b6634 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 new file mode 100644 index 0000000..d2c2e49 --- /dev/null +++ b/src/rust-2021/c-string-literals.md @@ -0,0 +1,155 @@ + + +# 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( + b"unicode characters \xce\xb1\xce\xb2\xce\xb3 encoded as UTF-8\0" + ) + .unwrap() +); +// ↓ 訳: 文字列は複数行にわたることができます +assert_eq!( + c"strings can continue \ + on multiple lines", + CStr::from_bytes_with_nul(b"strings can continue on multiple lines\0").unwrap() +); +``` + + + +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