dco*_*les 6 arrays static compile-time-constant rust
我有一个 C 库,它需要明确定义字符串长度的字符串类型:
#[repr(C)]
pub struct FFIStr {
len: usize,
data: *const u8,
}
Run Code Online (Sandbox Code Playgroud)
因为这种类型被用作静态类型,所以我想要一种使用 const 函数或宏(而不是手动设置len)安全地声明它的方法。
我的第一次尝试是使用宏len(),但是在1.39.0 之前的版本中,不可能将切片的长度作为 const fn 获取:
macro_rules! ffi_string {
($x:expr) => {
FFIStr { len: $x.len(), data: $x as *const u8 }
};
}
#[no_mangle]
pub static mut HELLO_WORLD: FFIStr = ffi_string!(b"Hello, world!");
Run Code Online (Sandbox Code Playgroud)
error: core::slice::<impl [T]>::len` is not yet stable as a const function
我的第二次尝试是使用std::mem::size_of<T>,但似乎没有办法在不使用泛型的情况下获取静态数组的类型:
const fn ffi_string<T>(s: &'static T) -> FFIStr {
FFIStr { len: ::std::mem::size_of::<T>(), data: s as *const _ as *const _ }
}
#[no_mangle]
pub static mut HELLO_WORLD: FFIStr = ffi_string(b"Hello, world!");
Run Code Online (Sandbox Code Playgroud)
虽然这有效(令人惊讶),但它非常容易被误用,因为它会疯狂地将您传递给*const u8.
似乎const_generics将是一个很好的解决方案,但它们目前不稳定:
const fn ffi_string<const SIZE: usize>(s: &'static [u8; SIZE]) -> FFIStr {
FFIStr { len: SIZE, data: s as *const u8 }
}
#[no_mangle]
pub static mut X: FFIStr = ffi_string(b"Hello, world!");
Run Code Online (Sandbox Code Playgroud)
error[E0658]: const generics are unstable
有没有更好的方法在编译时确定静态数组的大小?
在 Rust 1.39.0 中,[T]::len稳定为 const 函数,现在使其变得简单:
const ARRAY: [i32; 3] = [1, 2, 3];
const ARRAY_SIZE: usize = ARRAY.len();
fn main() {
assert_eq!(3, ARRAY_SIZE);
}
Run Code Online (Sandbox Code Playgroud)
在 Rust 的早期版本中,这是一种基于常见 CARRAY_SIZE宏的方法:
macro_rules! array_size {
($x:expr) => (
(size_of_val($x) / size_of_val(&$x[0]))
)
}
const fn size_of_val<T>(_: &T) -> usize {
std::mem::size_of::<T>()
}
fn main() {
assert_eq!(3, array_size!(&[1, 2, 3]));
assert_eq!(13, array_size!(b"Hello, world!"));
}
Run Code Online (Sandbox Code Playgroud)
它使用 const 泛型函数size_of_val<T>来确定类型,从而确定通过引用传递的值的大小(内置函数std::mem::size_of_val不是 const)。
注意:这对于大小为 0 的数组不起作用。这可以通过使用来修复,但size_of_val($x) / size_of_val(unsafe { &*$x.as_ptr() })代价是错误地接受非数组类型(例如&String)。
| 归档时间: |
|
| 查看次数: |
1856 次 |
| 最近记录: |