在C语言中,我们可以通过指针访问结构的各个元素。我们如何在Rust中做同样的事情?
下面的代码显示了如何使用C中的指针访问元素。
#include <stdio.h>
#include <stdlib.h>
typedef struct __attribute__ ((packed)) {
int a;
int b;
int c;
} Data;
Data* new_data(const int a, const int b, const int c) {
Data* data = malloc(sizeof(Data));
data->a = a;
data->b = b;
data->c = c;
return data;
}
int main(int argc, char* argv[]) {
Data* data = new_data(23, 35, 12);
// accessing elements via pointers
printf("\n --- Using pointers ---\n");
printf("a: %d\n", *((int*)data + 0));
printf("b: %d\n", *((int*)data + 1));
printf("c: %d\n", *((int*)data + 2));
// using pointer magic
printf("\n --- Using pointer magic ---\n");
printf("b: %d\n", *((int*)((char*)data + sizeof(int))));
printf("c: %d\n", *((int*)((char*)data + sizeof(int) * 2)));
// accessing elements via name
printf("\n --- Using names ---\n");
printf("a: %d\n", data->a);
printf("b: %d\n", data->b);
printf("c: %d\n", data->c);
free(data);
return 0;
}
上面的代码是使用gcc
编译的,我知道它也是特定于平台的,但这与我无关。以下是我目前在Rust中拥有的东西。
struct Data<T> {
el: Vec<T>
}
impl <T> Data<T> where T: Copy {
fn new(a: T, b: T, c: T) -> Self {
let mut s = Self { el: Vec::with_capacity(3) };
s.el.push(a);
s.el.push(b);
s.el.push(c);
return s;
}
fn get_a(&self) -> T { self.el[0] }
fn get_b(&self) -> T { self.el[1] }
fn get_c(&self) -> T { self.el[2] }
}
fn main() {
let mut data = Data::new(23, 35, 12);
println!("data capacity: {:?}", data.el.capacity());
println!("a: {:?}", data.get_a());
println!("b: {:?}", data.get_b());
println!("c: {:?}", data.get_c());
}
我想能够使用struct Data<T> {
a: T,
b: T,
c: T
}
并通过它们的索引访问每个元素。
最佳答案
在一般情况下,今天在Rust中无法正确执行此操作。 但是,您的特定结构避免了一些最严重的问题,因此可以安全地将整个结构作为借来的切片(&[T]
)借用。为此,您需要做三件事:
repr(C)
,而不是repr(packed)
!压缩的结构是未对齐的,并且引用必须始终正确对齐。isize::MAX
。slice::from_raw_parts
从&[T]
借用&Data<T>
。有关声音合理性的逐点说明,请参阅Is it legal to cast a struct to an array?
#[repr(C)]
struct Data<T> {
pub a: T,
pub b: T,
pub c: T,
}
impl<T> Data<T>
where
T: Copy,
{
fn new(a: T, b: T, c: T) -> Self {
Data { a, b, c }
}
// N.B. you could also implement `AsRef<[T]>` and/or `Borrow<[T]>`, which
// are used frequently in generic code
fn as_slice(&self) -> &[T] {
assert!(std::mem::size_of::<Self>() <= isize::MAX as _);
// This `unsafe` block was copied from Stack Overflow without proving
// its use is correct in this context, so it's almost certainly wrong
unsafe { std::slice::from_raw_parts(self as *const _ as *const T, 3) }
}
}
关于c - 是否可以使用Rust中的指针访问结构的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64307184/