我可以使用这种技术防止破坏抗锯齿规则吗?

时间:2012-06-01 14:37:35

标签: c++

如果我没记错的话,写入FastKey::key然后从FastKey::keyValue读取将是未定义的行为:

struct Key {
    std::array<uint8_t, 6> MACAddress;
    uint16_t EtherType;
};

union FastKey {
    Key key;
    uint64_t keyValue;
};

但是,有人告诉我,如果我将char数组添加到union中,那么UB将被清除:

union FastKey {
    Key key;
    uint64_t keyValue;
    char fixUB[sizeof(Key)];
};

这是真的吗?

修改

像往常一样,我的理解是错误的。根据我收集的新信息,我认为我可以将密钥作为uint64_t这样的值获取:

struct Key {
    std::array<uint8_t, 6> MACAddress;
    uint16_t EtherType;
};

union FastKey {
    Key key;
    unsigned char data[sizeof(Key)];
};

inline uint64_t GetKeyValue(FastKey fastKey)
{
    uint64_t key = 0;
    key |= size_t(fastKey.data[0]) << 56;
    key |= size_t(fastKey.data[1]) << 48;
    key |= size_t(fastKey.data[2]) << 40;
    key |= size_t(fastKey.data[3]) << 32;
    key |= size_t(fastKey.data[4]) << 24;
    key |= size_t(fastKey.data[5]) << 16;
    key |= size_t(fastKey.data[6]) << 8;
    key |= size_t(fastKey.data[7]) << 0;
    return key;
}

我怀疑这与原始版本一样快。随意纠正我。

更新

@Steve Jessop我实现了一个quick benchmark来测试memcpy与我的解决方案的性能。我不是基准测试专家,因此代码中可能存在愚蠢的错误导致错误的结果。但是,如果代码是正确的,那么memcpy似乎要慢得多。

注意:似乎基准测试是错误的,因为计算快速键时间的时间总是为零。我会看看是否可以修复它。

1 个答案:

答案 0 :(得分:4)

不,如果你有一个uint64_t对象,那么阅读Key仍有UB。 UB不是读char,因为别名规则中char有例外。添加数组不会将异常传播到其他类型。

编辑中的版本似乎很好(虽然我使用unsigned char),但现在它比使用reinterpret_castKey*的{​​{1}}更复杂或unsigned char*