У меня есть код, который делает XOR на блоках данных с помощью указателей, что быстро, но я бы хотел избавиться от «небезопасного» требования к сборке. Если я изменил его на использование LayoutKind.Explicit и наложил «ulong []» поверх «byte []», я в основном делаю то же, что и с указателями, но, похоже, это так же опасно. Основное различие между этими двумя заключается в том, что «безопасная» версия составляет около 1/2 скорости «небезопасной» версии.Допустимо ли использовать LayoutKind.Explicit, чтобы обойти использование «небезопасных» указателей?
Действительно ли это законный способ обхода «небезопасной» сборки или доступ к байту [] 1 байт за один раз - единственный законный способ сделать это безопасным образом?
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);
}
}