2

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

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

union FastKey {
    Key key;
    uint64_t keyValue;
};

但是,有人告诉我,如果我将 char 数组添加到联合中,那么 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 我实施了一个快速基准测试来测试 memcpy 与我的解决方案的性能。我不是基准测试专家,因此代码中可能存在愚蠢的错误导致错误的结果。但是,如果代码正确,那么 memcpy 似乎要慢得多。

注意:基准测试似乎是错误的,因为计算快键时间的时间始终为零。我看看能不能修好。

4

1 回答 1

4

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

编辑中的版本看起来不错(尽管我会使用unsigned char),但现在它比仅使用reinterpret_castfrom Key*tounsigned char*或 a更复杂memcpy

于 2012-06-01T14:44:42.847 回答