Ale*_*der 19 string casting vector rust
有没有更好的方式来投Vec<i8>
来Vec<u8>
鲁斯特除了这两个人?
std::transmute
根据文档,(1) 很慢,(2) 是“转化应该是绝对的最后手段” 。
可能有一点背景知识:我Vec<i8>
从不安全的gl::GetShaderInfoLog()调用中得到了一个,并希望通过使用String::from_utf8()
.
use*_*342 18
其他答案为从Vec<i8>
. 要回答提出的问题,可以在不复制或转换向量的情况下Vec<u8>
从a 中的数据创建 a Vec<i8>
。正如@trentcl 所指出的,直接转换向量构成未定义的行为,因为Vec
允许对不同的类型有不同的布局。
unsafe
传输向量数据而不复制它的正确(尽管仍然需要使用)方法是:
*mut i8
指向向量中数据的指针,以及它的长度和容量Vec::from_raw_parts
构建一个新的向量,给它一个*mut u8
强制转换的指针——这是不安全的部分,因为我们保证指针包含有效和初始化的数据,并且它没有被其他对象使用,等等。这不是 UB,因为 newVec
从一开始就被赋予了正确类型的指针。代码(游乐场):
fn vec_i8_into_u8(v: Vec<i8>) -> Vec<u8> {
// ideally we'd use Vec::into_raw_parts, but it's unstable,
// so we have to do it manually:
// first, make sure v's destructor doesn't free the data
// it thinks it owns when it goes out of scope
let mut v = std::mem::ManuallyDrop::new(v);
// then, pick apart the existing Vec
let p = v.as_mut_ptr();
let len = v.len();
let cap = v.capacity();
// finally, adopt the data into a new Vec
unsafe { Vec::from_raw_parts(p as *mut u8, len, cap) }
}
fn main() {
let v = vec![-1i8, 2, 3];
assert!(vec_i8_into_u8(v) == vec![255u8, 2, 3]);
}
Run Code Online (Sandbox Code Playgroud)
tre*_*tcl 11
transmute
on aVec
总是 100% 错误,导致未定义的行为,因为Vec
未指定的布局。但是,正如您链接的页面也提到的,您可以使用原始指针并Vec::from_raw_parts
正确执行此操作。user4815162342 的回答显示了如何。
(std::mem::transmute
是 Rust 标准库中唯一一个其文档主要由如何不使用它的建议组成的项目。按照你的意愿去做。)
但是,在这种情况下,from_raw_parts
也是不必要的。在 Rust 中处理 C 字符串的最佳方法是使用std::ffi
,CStr
和 中的包装器CString
。可能有更好的方法可以将其应用到您的实际代码中,但您可以使用以下一种方法将CStr
aVec<c_char>
作为 a借用&str
:
const BUF_SIZE: usize = 1000;
let mut info_log: Vec<c_char> = vec![0; BUF_SIZE];
let mut len: usize;
unsafe {
gl::GetShaderInfoLog(shader, BUF_SIZE, &mut len, info_log.as_mut_ptr());
}
let log = Cstr::from_bytes_with_nul(info_log[..len + 1])
.expect("Slice must be nul terminated and contain no nul bytes")
.to_str()
.expect("Slice must be valid UTF-8 text");
Run Code Online (Sandbox Code Playgroud)
请注意,unsafe
除了调用 FFI 函数外,没有其他代码;您还可以使用with_capacity
+ set_len
(如在wasmup 的回答中)跳过Vec
将 1000 个零初始化,并用于from_bytes_with_nul_unchecked
跳过检查返回字符串的有效性。