从 Rust 1.77 版本开始,可以使用带有 c
或 cr
前缀的 C 字符串字面量语法来编写 C 字符串。
以前,要正确生成一个能与以 NUL 字节结尾的 C API 互操作的有效字符串字面量是具有挑战性的。 cstr
crate 是一个流行的解决方案,但这需要编译一个相当昂贵的 proc-macro。现在,可以使用字面量语法直接编写 C 字符串,这将生成一个类型为 &core::ffi::CStr
的值,该值会自动以 NUL 字节结尾。
#![allow(unused)]
fn main () {
use core::ffi::CStr;
assert_eq! (c"hello" , CStr::from_bytes_with_nul(b"hello\0" ).unwrap());
assert_eq! (
c"byte escapes \xff work" ,
CStr::from_bytes_with_nul(b"byte escapes \xff work\0" ).unwrap()
);
assert_eq! (
c"unicode escapes \u{00E6} work" ,
CStr::from_bytes_with_nul(b"unicode escapes \xc3\xa6 work\0" ).unwrap()
);
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 字符串不允许内部有 NUL 字节(例如使用 \0
转义)。
与常规字符串类似,C 字符串也支持带有 cr
前缀的“原始”语法。这些原始 C 字符串不处理反斜杠转义,这可以使编写包含反斜杠的字符串更容易。双引号可以通过用 #
字符包围引号来包含。可以使用多个 #
字符来避免与内部 "#
序列产生歧义。
#![allow(unused)]
fn main () {
assert_eq! (cr"foo" , c"foo" );
assert_eq! (cr#""foo""# , c"\"foo\"" );
assert_eq! (cr##""foo"#"## , c"\"foo\"#" );
assert_eq! (cr"C:\foo" , c"C:\\foo" );
}
更多详情请参阅 参考手册 。
仅当宏可能假设了看起来类似于 c"…"
或 cr"…"
的标记序列时,才需要进行迁移。在 2021 版本之前,这些标记会被标记为两个单独的标记,但在 2021 版本中则会显示为单个标记。
作为 2021 版本 语法保留 的一部分,任何可能遇到此问题的宏输入都应该发出 rust_2021_prefixes_incompatible_syntax
迁移 lint 的警告。有关更多详细信息,请参阅该章节。