'\0'表示,由 C 编译器自动添加。char表示ASCII和UTF-8编码,wchar_t表示UTF-16等“宽”字符编码。char *参数,该参数表示指向字符串中的第一个字符(即存储该字符串的数组的第一个元素)。由于传递给函数的是第一个元素的地址,因此该函数并不知道数组有多大,只能依靠空终止符来判断何时停止处理。char *。在大多数编译器中,将字符串字面量直接分配给指针后,字符串常量被存储于初始化数据段的只读(.roadata)区域,而指针变量被存储于读写区域中,也就是说可以更改指针以指向其它内容,但不能更改字符串常量的内容。因此,仅当不需要在程序的后期修改字符串时,应使用char *方式声明。char []。将字符串对字节数组进行初始化后,在函数执行时会被拷贝到栈区或堆区(使用 malloc),这时数组的内容是可以被修改的。因此,对于需要修改的字符串,应使用char[] 方式声明。同时由于 C 指针是一个用数值表示的地址,因此,可以对指针执行算术运算来修改字符串。// ffi/example_01/csrc/hello.c
// basic string - char pointer
char *str;
str = "hello"; // Stored in read only part of data segment
*(str+1) = 'i'; // Segmentation fault error: trying to modify read only memory
char hello_s[] = "hello"; // Stored in stack segment
*(hello_s+0) = 'H'; // No problem: String is now Hello
printf("new string is %s\n", hello_s);

str:这是 Rust 语言核心中仅有的一种字符串类型,Rust 标准库中提供了其它的字符串类型。&str:表示不可变的 UTF-8 编码的字节序列,它是str类型的引用属于引用类型;String:表示可变的字符串,拥有所有权,其本质是一个成员变量是Vec<u8>类型的结构体;CStr:表示以空字符终止的 C 字符串或字节数组的借用,属于引用类型。一般用于和 C 语言交互,由 C 分配并被 Rust 借用的字符串;CString:表示拥有所有权的,中间没有空字节,以空字符终止的字符串类型。一般用于和 C 语言交互时,由 Rust 分配并传递给 C 的字符串;char类型来表示,而使用u8来表示字节类型。注意:定义字符是使用单引号,用双引号定义的是字符串常量。print_str和change_str两个函数,其参数均为 C 端生成的一个字符串,分别实现打印和修改该字符串的功能;generate_str函数,其返回值是 Rust 端生成的一个字符串,以及free_str函数供 C 端调用者将字符串返回给 Rust 释放内存;void print_str(char *str);
char *change_str(char str[]);
char *generate_str();
void free_str(char *);
use std::os::raw::c_char;
use std::ffi::{CStr, CString};
#[no_mangle]
pub extern "C" fn print_str(s: *const c_char) {
let slice = unsafe {
assert!(!s.is_null());
CStr::from_ptr(s)
};
let r_str = slice.to_str().unwrap();
println!("Rust side print: {:?}", r_str);
}
#[no_mangle]
pub extern "C" fn change_str(s: *mut c_char) -> *mut c_char {
let mut string = unsafe {
assert!(!s.is_null());
CStr::from_ptr(s).to_string_lossy().into_owned()
};
string.push_str(" World!");
println!("Rust side change: {:?}", string);
let c_str_changed = CString::new(string).unwrap();
c_str_changed.into_raw()
}
#[no_mangle]
pub extern "C" fn generate_str() -> *mut c_char {
let ping = String::from("ping");
println!("Rust side generate: {:?}", ping);
let c_str_ping = CString::new(ping).unwrap();
c_str_ping.into_raw()
}
#[no_mangle]
pub extern "C" fn free_str(s: *mut c_char) {
unsafe {
if s.is_null() {
return;
}
CString::from_raw(s)
};
}
std::ffi::CStr提供的from_ptr方法包装 C 的字符串指针,它基于空字符'\0'来计算字符串的长度,并可以通过它将外部 C 字符串转换为 Rust 的 &str和String。std::ffi::CString提供的一对方法into_raw和from_raw可以进行原始指针转换,由于将字符串的所有权转移给了调用者,所以调用者必须将字符串返回给 Rust,以便正确地释放内存。--show-reachable=yes 选项进行定位,发现均发生在 C 端调用 Rust 的 print_str 函数处。谷歌找了半天原因,最终发现原来是跟 Rust 的行缓冲区 stdout 有关。vec,它只执行一次,每次调用时重用现有缓冲区。因为我们此处是从 C 端运行,并不能控制其 main 函数,因此它将不会被释放,这就是 valgrind 报告的原因所在。我们知道只是打印字符串到控制台,所以这个泄露不用太担心。原文作者:Rust语言中文社区;如有侵权,请联系管理员删除。