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

いいえ、まだ UB があるオブジェクトがあるuint64_t場合は a を読み取ります。KeyUB ではないのは、 a を読み取ることです。これは、エイリアシング ルールにchar例外があるためです。char配列を追加しても、例外は他の型に伝播されません。

編集のバージョンは問題ないように見えますが (私は を使用しますunsigned char)、今では from や . を使用するよりも複雑になっreinterpret_castていKey*ます。unsigned char*memcpy

于 2012-06-01T14:44:42.847 に答える