В .NET-объектах (из которых массивы являются разновидностями) всегда выравнивают на основе размера указателя (например, 4-байтовое или 8-байтовое выравнивание). Таким образом, указатели и массивы объектов всегда выровнены в .NET.
Код в ответе Михаэля Грачика проверяет выравнивание по индексу, потому что, хотя сам массив выровнен, так как это массив Int32, отдельные нечетные индексы не будут выровнены в 64-битных системах. В 32-битных системах все индексы массива Int32 будут выровнены.
Технически, этот метод мог бы быть быстрее, если бы он проверял битность процесса. В 32-битных процессах не нужно выполнять проверку выравнивания для массивов Int32. Поскольку все индексы будут выровнены по словам, а в этом случае указатели также имеют длину слова.
Следует также отметить, что разыменование указателя в .NET не требует выравнивания. Тем не менее, это будет медленнее. например если у вас есть действительный указатель байта *, который указывает на данные длиной не менее восьми байт, вы можете привести его к long * и получить значение:
unsafe
{
var data = new byte[ 16 ];
fixed ( byte* dataP = data )
{
var misalignedlongP = ( long* ) ( dataP + 3 );
long value = *misalignedlongP;
}
}
Читая исходный код .NET, вы можете видеть, что Microsoft иногда учитывает выравнивание, а часто - нет. Примером может служить внутренний метод System.Buffer.Memmove
(см. https://referencesource.microsoft.com/#mscorlib/system/buffer.cs,c2ca91c0d34a8f86).. Этот метод имеет пути кода, которые преобразуют байт * в long без каких-либо проверок выравнивания в нескольких местах, и вызывающие методы также не проверяют выравнивание.