struct - 选项类型是否小于包装类型加上 boolean 值?

标签 struct rust boolean padding optional

use std::mem::size_of;

struct Position {
    x: f32,
    y: f32,
    z: f32,
}

struct PoolItem {
    entity_id: u32, // 4 bytes
    used: bool, // 1 bytes + 3 (padding)
    component: Position, // 12 bytes
}


assert_eq!(size_of::<u32>(), 4);
assert_eq!(size_of::<Position>(), 12);
assert_eq!(size_of::<PoolItem>(), 20);

如您所见,这种结构的长度为20个字节。 Position实际上是 optional ,并且取决于used

使用 Option 是否会消除对used字段的需要并将结构大小减小到16个?

struct PoolItem {
    entity_id: u32, // 4 bytes
    component: Option<Position>, // 12 bytes ?
}

如果是这样,如何实现这种行为才能实现Option

我对Playground的测试似乎表明它不起作用。为什么?

最佳答案

Option<Position>需要将状态(SomeNone)存储在某个位置,并且由于Position已经包含12个字节的信息,因此需要更多空间来存储它。通常这意味着它增加了一个额外的字节(加上填充)来存储状态,尽管在某些情况下内部类型具有已知的未使用状态。例如,引用可以指向地址0,因此Option<&'_ T>可以使用0作为None状态,并占用与&'_ T相同的字节数。但是,对于您的Position类型,情况并非如此。

如果您绝对需要PoolItem结构尽可能小,并且可以从entity_id字段中保留一位(例如最高位231),则可以使用它来存储状态:

const COMPONENT_USED_BIT: u32 = (1u32 << 31);

struct PoolItem {
    entity_id: u32, // lowest 31 bits = entity ID, highest bit = "component used"
    component: Position,
}

这可能会变得有些复杂,因为您需要确保特别对待该位,但是您可以编写一些简单的访问器方法来确保正确处理该特殊位。

impl PoolItem {
    /// Get entity ID, without the "component used" bit
    fn entity_id(&self) -> u32 {
        self.entity_id & !COMPONENT_USED_BIT
    }

    /// Set entity ID, keeping the existing "component used" bit
    fn set_entity_id(&mut self, entity_id: u32) {
        let component_used_bit = self.entity_id & COMPONENT_USED_BIT;
        self.entity_id = (entity_id & !COMPONENT_USED_BIT) | component_used_bit;
    }

    /// Get component if "component used" bit is set
    fn component(&self) -> Option<&Position> {
        if self.entity_id & COMPONENT_USED_BIT != 0 {
            Some(&self.component)
        } else {
            None
        }
    }

    /// Set component, updating the "component used" bit
    fn set_component(&mut self, component: Option<Position>) {
        if let Some(component) = component {
            self.component = component;
            self.entity_id |= COMPONENT_USED_BIT;
        } else {
            self.entity_id &= !COMPONENT_USED_BIT;
        }
    }
}

Playground example with tests

关于struct - 选项类型是否小于包装类型加上 boolean 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61043096/

相关文章:

c - 将文件中的数据分解为结构体

使用 C 将输入与 txt 文件中的数据进行比较

go - 在 Go 中附加到结构 slice

algorithm - 如何在不包含负值的情况下获取矩阵中的所有邻居索引?

在 C 中的链表中创建链接

rust - 如何更改 Piston2D/PistonWindow/GlutinWindow 中的光标图标?

parsing - 在 proc 宏派生上将属性转换为标识符

ruby - 如何使用 Ruby 在 CSV 中排除以 A、B 或 C 开头的行

java - 基于正面或反面的抛硬币总值(value)

java - 我显然对 boolean 值有疑问,基于文本的游戏