linked-list - 是否可以在 Rust 中将一个结构的内存与另一个结构相关联?

标签 linked-list rust binary-tree type-punning

我知道在 Rust 中,编译器不保证您按照声明的顺序获取结构数据,以节省内存(我也相信一些 C 代码优化器正在做同样的事情)。假设现在我有一个二叉树并想将其转换为双向链表。在 C 中,我会声明两个结构:

typedef struct tree{
    void* left_child;
    void* right_child;
    void* data;
}tree_t;

对于树,并且:

typedef struct list{
    void* before;
    void* after;
    void* data;
}list_t;

为链表。如果我现在想将树转换为列表,我可以就地执行此操作,我只需将树的内存与列表结构相关联并更改指针:

tree_t mytree;
/*fill tree*/
list_t *list_p;
list_p = (list_t)&mytree;
/*change pointers accordingly*/

但是我怎么能在 Rust 中做这样的事情呢?不使用 unsafe 代码是否可行? 直到现在我有了我的树:

struct TreeNode<'a, T> {
    left_child: BinaryTreeLink<'a, T>,
    right_child: BinaryTreeLink<'a, T>,
    data : &'a T,
}

type BinaryTreeLink<'a, T> = Option<Box<TreeNode<'a, T>>>;

列表将是:

struct ListNode<'a, T> {
    before: ListLink<'a, T>,
    after: ListLink<'a, T>,
    data : &'a T,
}

type ListLink<'a, T> = Option<Box<ListNode<'a, T>>>;

但我现在如何才能有效地转换它们呢?

最佳答案

But How can I do such a thing in Rust? Is it even possible without using unsafe code? Till now I have my tree

直接做同样的事情,您需要使用不安全的代码。函数 std::mem::transmute 完全符合您的要求。问题在于 Rust 中结构的布局是无法保证的,因此以下通常是未定义的行为:

use std::mem;
let list_link: Option<Box<ListNode<_>>> = unsafe { mem::transmute(tree_node) };

但是,您可以通过使用 C 表示强制结构的布局是可预测的来使其安全:

#[repr(C)]
struct TreeNode<'a, T> {
    left_child: BinaryTreeLink<'a, T>,
    right_child: BinaryTreeLink<'a, T>,
    data : &'a T,
}

#[repr(C)]
struct ListNode<'a, T> {
    before: ListLink<'a, T>,
    after: ListLink<'a, T>,
    data : &'a T,
}

您还需要将 #[repr(C)] 应用于内部类型 ListLinkBinaryTreeLink 的定义。


但是如何完全避免不安全的代码呢?如果您编写转换函数,消耗原始数据,优化器应该能够将其转换为空操作,因为它知道没有其他代码可以引用该数据内存。

<'a, T> impl From<ListNode<'a, T>> for TreeNode<'a, T> {
     fn from(other: ListNode<'a, T>) -> ListNode<'a, T>> {
         ListNode {
             before: other.left_child,
             after: other.right_child,
             data: other.data,
         }
     }
}

您绝对应该对此进行基准测试以确保,但优化器拥有将其变成空操作所需的所有信息,而且它很可能会。

关于linked-list - 是否可以在 Rust 中将一个结构的内存与另一个结构相关联?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54973814/

相关文章:

c - 反转链表 C

c - 为什么 gcc 说我有未声明的变量 'newNode'?

java - 链表测试....返回类型问题

enums - 如何在模式匹配中忽略类结构枚举变体的成员?

performance - 找出二叉树是否平衡或效率不高

c++ - 2 位输入的表达式树

链表中的Java自编程单链表

rust - 如何确保对象的生命周期不会超过其工厂

rust - 如何从 C 正确链接到 Rust 动态库?

java - 统计BST中小于X的节点数