pub struct CStr { /* private fields */ }
Expand description
借用的 C 字符串的表示形式。
此类型表示对以 n 结尾的字节数组的引用。
它可以从一个 &[u8]
切片安全地构建,或者从原始 *const c_char
不安全地构建。
然后可以通过执行 UTF-8 验证将其转换为 Rust &str
,或转换为拥有所有权的 CString
。
&CStr
对 CString
如同 &str
对 String
: 每对中的前者都是借用的引用; 后者是拥有的字符串。
请注意,此结构体不是 repr(C)
,不建议放置在 FFI 函数的签名中。
而是,FFI 函数的安全包装程序可以利用不安全的 CStr::from_ptr
构造函数为其他使用者提供安全的接口。
Examples
检查外部 C 字符串:
use std::ffi::CStr;
use std::os::raw::c_char;
extern "C" { fn my_string() -> *const c_char; }
unsafe {
let slice = CStr::from_ptr(my_string());
println!("string buffer size without nul terminator: {}", slice.to_bytes().len());
}
Run传递源自 Rust 的 C 字符串:
use std::ffi::{CString, CStr};
use std::os::raw::c_char;
fn work(data: &CStr) {
extern "C" { fn work_with(data: *const c_char); }
unsafe { work_with(data.as_ptr()) }
}
let s = CString::new("data data data data").expect("CString::new failed");
work(&s);
Run将外部 C 字符串转换为 Rust String
:
use std::ffi::CStr;
use std::os::raw::c_char;
extern "C" { fn my_string() -> *const c_char; }
fn my_string_safe() -> String {
let cstr = unsafe { CStr::from_ptr(my_string()) };
// 获取写时复制 Cow<'_, str>,然后保证新拥有所有权的字符串分配
String::from_utf8_lossy(cstr.to_bytes()).to_string()
}
println!("string: {}", my_string_safe());
RunImplementations§
source§impl CStr
impl CStr
1.0.0 (const: unstable) · sourcepub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr
pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr
用安全的 C 字符串包装器包装原始 C 字符串。
此函数将使用 CStr
包装器包装提供的 ptr
,从而允许检查和互操作非所有的 C 字符串。
由于调用了 slice::from_raw_parts
函数,原始 C 字符串的总大小必须小于 isize::MAX
字节` 在内存中。
Safety
-
ptr
指向的内存必须在字符串末尾包含一个有效的 nul 终止符。 -
ptr
必须是 valid 以读取最多包括空终止符的字节。 这尤其意味着:- 这个
CStr
的整个内存范围必须包含在一个分配的对象中! - 即使对于零长度的 cstr,
ptr
也必须为非空值。
- 这个
-
返回的
CStr
引用的内存在生命周期'a
的持续时间内不能发生可变的。
Note: 该操作原定为零成本投放,但 目前已通过预先计算长度来实现 字符串。不能保证总是这样。
Caveat
从使用中可以推断出返回切片的生命周期。 为防止意外滥用,建议将生命周期与生命周期中任何安全的来源联系起来,例如通过提供一个辅助函数,获取切片的宿主值的生命周期,或通过明确的注解法。
Examples
use std::ffi::{c_char, CStr};
extern "C" {
fn my_string() -> *const c_char;
}
unsafe {
let slice = CStr::from_ptr(my_string());
println!("string returned: {}", slice.to_str().unwrap());
}
Run#![feature(const_cstr_methods)]
use std::ffi::{c_char, CStr};
const HELLO_PTR: *const c_char = {
const BYTES: &[u8] = b"Hello, world!\0";
BYTES.as_ptr().cast()
};
const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) };
Run1.69.0 (const: 1.69.0) · sourcepub const fn from_bytes_until_nul(
bytes: &[u8]
) -> Result<&CStr, FromBytesUntilNulError>
pub const fn from_bytes_until_nul( bytes: &[u8] ) -> Result<&CStr, FromBytesUntilNulError>
从字节切片创建 C 字符串包装器。
此方法将从包含至少一个 nul 字节的任何字节切片创建 CStr
。
调用者不需要知道或指定 nul 字节的位置。
如果第一个字节是一个空字符,这个方法将返回一个空的 CStr
。
如果存在多个 nul 字符,则 CStr
将在第一个字符处结束。
如果切片末尾只有一个 nul 字节,则此方法等效于 CStr::from_bytes_with_nul
。
Examples
use std::ffi::CStr;
let mut buffer = [0u8; 16];
unsafe {
// 在这里,我们可能会调用一个不安全的 C 函数,它将字符串写入缓冲区。
let buf_ptr = buffer.as_mut_ptr();
buf_ptr.write_bytes(b'A', 8);
}
// 尝试从缓冲区中提取 C 以 nul 结尾的字符串。
let c_str = CStr::from_bytes_until_nul(&buffer[..]).unwrap();
assert_eq!(c_str.to_str().unwrap(), "AAAAAAAA");
Run1.10.0 (const: unstable) · sourcepub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError>
pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError>
从字节切片创建 C 字符串包装器。
在确保字节切片以 nul 终止并且不包含任何内部 nul 字节之后,此函数会将提供的 bytes
强制转换为 CStr
包装器。
如果 nul 字节可能不在末尾,则可以使用 CStr::from_bytes_until_nul
代替。
Examples
use std::ffi::CStr;
let cstr = CStr::from_bytes_with_nul(b"hello\0");
assert!(cstr.is_ok());
Run创建没有尾随 nul 终止符的 CStr
是错误的:
use std::ffi::CStr;
let cstr = CStr::from_bytes_with_nul(b"hello");
assert!(cstr.is_err());
Run使用内部 nul 字节创建 CStr
是错误的:
use std::ffi::CStr;
let cstr = CStr::from_bytes_with_nul(b"he\0llo\0");
assert!(cstr.is_err());
Run1.10.0 (const: 1.59.0) · sourcepub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr
从字节切片不安全地创建 C 字符串包装器。
此函数会将提供的 bytes
强制转换为 CStr
包装器,而无需执行任何健全性检查。
Safety
所提供的切片必须以 nul 结尾,并且不包含任何内部 nul 字节。
Examples
use std::ffi::{CStr, CString};
unsafe {
let cstring = CString::new("hello").expect("CString::new failed");
let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
assert_eq!(cstr, &*cstring);
}
Run1.0.0 (const: 1.32.0) · sourcepub const fn as_ptr(&self) -> *const c_char
pub const fn as_ptr(&self) -> *const c_char
返回此 C 字符串的内部指针。
返回的指针在 self
内一直有效,并且指向以 0 字节结尾的连续区域,以表示字符串的结尾。
返回指针的类型是 *const c_char
,它是 *const i8
还是 *const u8
的别名是平台特定的。
WARNING
返回的指针是只读的; 对其进行写入 (包括将其传递给进行写入的 C 代码) 会导致未定义的行为。
您有责任确保底层内存不会过早释放。例如,当在 unsafe
块中使用 ptr
时,以下代码将导致未定义的行为:
use std::ffi::CString;
// 不要这样做:
let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
unsafe {
// `ptr` 是悬垂的
*ptr;
}
Run发生这种情况是因为 as_ptr
返回的指针不携带任何生命周期信息,并且 CString
在 CString::new("Hello").expect("CString::new failed").as_ptr()
表达式计算后立即被释放。
要解决此问题,请将 CString
绑定到本地变量:
use std::ffi::CString;
let hello = CString::new("Hello").expect("CString::new failed");
let ptr = hello.as_ptr();
unsafe {
// `ptr` 有效,因为 `hello` 在作用域内
*ptr;
}
Run这样,hello
中 CString
的生命周期就包含了 ptr
和 unsafe
区块的生命周期。
1.0.0 (const: unstable) · sourcepub fn to_bytes_with_nul(&self) -> &[u8]
pub fn to_bytes_with_nul(&self) -> &[u8]
将此 C 字符串转换为包含尾随 0 字节的字节切片。
此函数与 CStr::to_bytes
等效,除了保留尾随的 nul 终止符而不是将其截断之外。
Note: 目前,此方法已实现为零费用强制转换,但是 计划在 future 中更改其定义以执行 每次调用此方法时的长度计算。
Examples
use std::ffi::CStr;
let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
assert_eq!(cstr.to_bytes_with_nul(), b"foo\0");
Run