2015-08-26 7 views
2

Извините за запутанное название, но я не могу придумать лучшего способа объяснить это.Почему BitConverter.ToInt32 читает один байт за раз, если данные не выровнены по заданному смещению?

При просмотре the source code из BitConverter недавно я наткнулся на странный сегмент кода:

public static unsafe int ToInt32(byte[] value, int startIndex) 
{ 
    fixed (byte* pbyte = &value[startIndex]) 
    { 
     if (startIndex % 4 == 0) // data is aligned 
      return *((int*)pbyte); 
     else 
     { 
      if (IsLittleEndian) 
      { 
       return (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24); 
      } 
      else 
      { 
       return (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));       
      } 
     } 
    } 
} 

Как литья pbyte к int* (строка 6) нарушают выравнивание данных в этом случае? Я оставил его для краткости, но код имеет правильную проверку аргументов, поэтому я уверен, что это не может быть нарушение доступа к памяти. Означает ли он точность при бросании?

Другими словами, почему не может код быть упрощена:

public static unsafe int ToInt32(byte[] value, int startIndex) 
{ 
    fixed (byte* pbyte = &value[startIndex]) 
    { 
     return *(int*)pbyte; 
    } 
} 

Edit:Here это раздел кода в вопросе.

+1

Операции с данными, выровненными на границе размера данных, выполняются быстрее, а на некоторых процессорах доступ к неприсоединенным словам/dwords/float/doubles - это доступность доступа (комментарий, так как у меня нет хорошей ссылки). –

+0

@AlexeiLevenkov Тем не менее, вы создаете две дополнительные ветви, несколько побитовых операций, * и * разыменование 'pbyte + 1',' pbyte + 2' и т. Д. (3 из которых не будут выровнены), чтобы вы могли избегайте этого неприсоединения. Кажется, это довольно переполняет меня. –

+0

Не уверен в вашем комментарии - есть процессоры, которые вы не можете получить без выравнивания 'int' - http://stackoverflow.com/questions/1237963/alignment-along-4-byte-boundaries - так какая альтернативная реализация вы предлагаете по сравнению с чтением байт по байт? –

ответ

1

Держу пари, что это имеет отношение к этой части §18.4 в версии 5.0 C# спецификации (курсив мой):

Когда один тип указателя преобразуется в другой, если полученный указатель неправильно выровнен для указанного типа, поведение не определено, если результат разыменован.

Постепенное копирование в случае «без выравнивания» выполняется, чтобы не полагаться на явно неопределенное поведение.