Struct core::ffi::CStr

1.64.0 · source ·
pub struct CStr { /* private fields */ }
Expand description

借用的 C 字符串的表示形式。

此类型表示对以 n 结尾的字节数组的引用。 它可以从一个 &[u8] 切片安全地构建,或者从原始 *const c_char 不安全地构建。 然后可以通过执行 UTF-8 验证将其转换为 Rust &str,或转换为拥有所有权的 CString

&CStrCString 如同 &strString: 每对中的前者都是借用的引用; 后者是拥有的字符串。

请注意,此结构体不是 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());
Run

Implementations§

source§

impl CStr

1.0.0 (const: unstable) · source

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) };
Run
1.69.0 (const: 1.69.0) · source

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");
Run
1.10.0 (const: unstable) · source

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());
Run
1.10.0 (const: 1.59.0) · source

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);
}
Run
1.0.0 (const: 1.32.0) · source

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 返回的指针不携带任何生命周期信息,并且 CStringCString::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

这样,helloCString 的生命周期就包含了 ptrunsafe 区块的生命周期。

1.71.0 (const: 1.71.0) · source

pub const fn is_empty(&self) -> bool

如果 self.to_bytes() 的长度为 0.

Examples
use std::ffi::CStr;

let cstr = CStr::from_bytes_with_nul(b"foo\0")?;
assert!(!cstr.is_empty());

let empty_cstr = CStr::from_bytes_with_nul(b"\0")?;
assert!(empty_cstr.is_empty());
Run
1.0.0 · source

pub fn to_bytes(&self) -> &[u8]

将此 C 字符串转换为字节片。

返回的切片将不包含此 C 字符串具有的尾随 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(), b"foo");
Run
1.0.0 (const: unstable) · source

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
1.4.0 · source

pub fn to_str(&self) -> Result<&str, Utf8Error>

如果 CStr 包含有效的 UTF-8,则产生 &str 切片。

如果 CStr 的内容是有效的 UTF-8 数据,该函数将返回相应的 &str 切片。

否则,它将返回错误,并详细说明 UTF-8 验证失败的位置。

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_str(), Ok("foo"));
Run

Trait Implementations§

1.7.0 · source§

impl AsRef<CStr> for CStr

source§

fn as_ref(&self) -> &CStr

将此类型转换为 (通常是推断的) 输入类型的共享引用。
1.3.0 · source§

impl Debug for CStr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

使用给定的格式化程序格式化该值。 Read more
1.10.0 · source§

impl Default for &CStr

source§

fn default() -> Self

返回类型的 “默认值”。 Read more
source§

impl Hash for CStr

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

将该值输入给定的 HasherRead more
1.47.0 · source§

impl Index<RangeFrom<usize>> for CStr

§

type Output = CStr

索引后返回的类型。
source§

fn index(&self, index: RangeFrom<usize>) -> &CStr

执行索引 (container[index]) 操作。 Read more
1.0.0 · source§

impl Ord for CStr

source§

fn cmp(&self, other: &CStr) -> Ordering

此方法返回 selfother 之间的 OrderingRead more
1.0.0 · source§

impl PartialEq<CStr> for CStr

source§

fn eq(&self, other: &CStr) -> bool

此方法测试 selfother 值是否相等,并由 == 使用。
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

此方法测试 !=。 默认实现几乎总是足够的,并且不应在没有充分理由的情况下被覆盖。
1.0.0 · source§

impl PartialOrd<CStr> for CStr

source§

fn partial_cmp(&self, other: &CStr) -> Option<Ordering>

如果存在,则此方法返回 selfother 值之间的顺序。 Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

此方法测试的内容少于 (对于 selfother),并且由 < 操作员使用。 Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

此方法测试小于或等于 (对于 selfother),并且由 <= 运算符使用。 Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

此方法测试大于 (对于 selfother),并且由 > 操作员使用。 Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

此方法测试是否大于或等于 (对于 selfother),并且由 >= 运算符使用。 Read more
1.0.0 · source§

impl Eq for CStr

Auto Trait Implementations§

§

impl RefUnwindSafe for CStr

§

impl Send for CStr

§

impl !Sized for CStr

§

impl Sync for CStr

§

impl Unpin for CStr

§

impl UnwindSafe for CStr

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

获取 selfTypeIdRead more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

从拥有的值中一成不变地借用。 Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

从拥有的值中借用。 Read more