2

ポインターを使用してデータのブロックに対して XOR を実行するコードがありますが、これは高速ですが、アセンブリの「安全でない」要件を取り除きたいと考えています。LayoutKind.Explicit を使用するように変更し、「ulong[]」を「byte[]」の上に重ねると、基本的にはポインターで行ったのと同じことをしていますが、同じように危険なようです。これら 2 つの主な違いは、「安全」バージョンの速度が「安全でない」バージョンの約 1/2 であることです。

これは「安全でない」アセンブリを回避するための正当な方法ですか、それとも一度に 1 バイトずつ byte[] にアクセスすることが安全な方法でこれを行う唯一の正当な方法ですか?

private unsafe static void UnsafeEncode(
    byte[] buffer, int bufPos, ulong[] vector, int SectionLength, byte vectorIndex)
{
    fixed (byte* p = &buffer[bufPos])
    {
        ulong* pCur = (ulong*)p;
        ulong* pEnd = pCur + SectionLength;
        while (pCur < pEnd)
        {
            *pCur ^= vector[vectorIndex++];
            pCur++;
        }
    }
}

[StructLayout(LayoutKind.Explicit)]
private struct ArrayOverlay
{
    [FieldOffset(0)]
    public byte[] Bytes;
    [FieldOffset(0)]
    public ulong[] Longs;
}

private static void SafeEncode(
    byte[] buffer, int bufPos, ulong[] vector, int SectionLength, byte vectorIndex)
{
    var overlay = new ArrayOverlay { Bytes = buffer };
    int shiftleft = (bufPos & 7) << 3;
    int pos = bufPos >> 3;
    if (shiftleft == 0)
    {
        for (int i = 0; i < SectionLength; i++)
            overlay.Longs[i + pos] ^= vector[vectorIndex++];
    }
    else
    {
        int shiftright = (64 - shiftleft) & 63;
        ulong oldVec = 0;
        for (int i = 0; i < SectionLength; i++)
        {
            var vec = vector[vectorIndex++];
            overlay.Longs[i + pos] ^= (vec << shiftleft) | (oldVec >> shiftright);
            oldVec = vec;
        }
        overlay.Longs[SectionLength + pos] ^= (oldVec >> shiftright);
    }
}
4

1 に答える 1