I'm currently trying to translate a C program to Rust.
我正在尝试将一个C程序翻译成Rust。
The C programm has following structures (boiled down to MRE):
C程序具有以下结构(归结为MRE):
typedef struct {
bool isActive;
uint32_t value;
} tMyInnerStruct;
typedef struct {
tMyInnerStruct inner1;
tMyInnerStruct inner2;
} tMyStruct;
and in a function I would do the following pointer magic:
在一个函数中,我将执行以下指针魔术:
void myFunction()
{
tMyStruct myStruct = initMyStuct();
tMyInnerStruct *pActiveInner = &myStruct.inner1;
// Do something with pActiveInner (pointing to inner1), like setting value...
changeActiveStruct(&myStruct, &pActiveInner);
// Do something with pActiveInner (pointing to inner2), like setting value...
}
void changeActiveStruct( tMyStruct *pMyStruct, tMyInnerStruct **ppActiveInner )
{
if ( &pMyStruct->inner1 == *ppActiveInner ) {
*ppActiveInner = &pMyStruct->inner2;
} else {
*ppActiveInner = &pMyStruct->inner1;
}
}
No my question is: How would I achieve the same in Rust?
不,我的问题是:我将如何在铁锈中实现同样的目标?
What I've tried so far in Rust:
到目前为止,我在《铁锈》中尝试过的是:
#[derive(Default)]
struct MyInnerStruct {
is_active: bool,
value: u32,
}
#[derive(Default)]
struct MyStruct {
inner1: MyInnerStruct,
inner2: MyInnerStruct,
}
impl MyStruct {
fn change_active(&mut self, active: &MyInnerStruct) -> &mut MyInnerStruct {
if &self.inner1 as *const _ == active as *const _ {
&mut self.inner2
} else {
&mut self.inner1
}
}
}
fn main() {
let mut my_struct: MyStruct = Default::default();
let mut active = &mut my_struct.inner1;
active = my_struct.change_active(active);
// The above complains, that my_struct cannot be borrowed mutable more than once...
}
更多回答
优秀答案推荐
You can accompilsh the same thing by using a pointer as argument instead of a reference. Because of the order that arguments and the receiver are evaluated in, you have to convert to a pointer ahead of the call and can't do it in the parameter list but this works:
您可以通过使用指针作为参数而不是引用来编译相同的内容。由于参数和接收器的求值顺序,您必须转换为调用之前的指针,并且不能在参数列表中这样做,但这是可行的:
impl MyStruct {
fn change_active(&mut self, active: *const MyInnerStruct) -> &mut MyInnerStruct {
if &self.inner1 as *const _ == active {
&mut self.inner2
} else {
&mut self.inner1
}
}
}
fn main() {
let mut my_struct: MyStruct = Default::default();
let mut active = &mut my_struct.inner1;
active = {
let active = active as *const _;
my_struct.change_active(active)
};
}
Playground
操场
Minor detail, change_active
does no longer seem like an apropriate name since the Rust version doesn't actually change active
maybe new_active
or something else still is a better name for the method
次要细节,CHANGE_ACTIVE看起来不再像是一个合适的名称,因为Rust版本实际上不会更改ACTIVE可能是NEW_ACTIVE或其他名称仍然是该方法的更好名称
更多回答
Thanks, this is what I was searching for :-) The cast during the comparison was already a hint, but I'm not so familiar with the pointers in Rust. The only drawback in my opinion, is the scoped shadowing of the active variable, as it's not a one-liner ;-)
谢谢,这就是我正在寻找的:-)对比过程中的演员阵容已经是一个提示,但我对《铁锈》中的指针不是很熟悉。在我看来,唯一的缺点是活动变量的作用域跟踪,因为它不是一行程序;-)
我是一名优秀的程序员,十分优秀!