Тестирование на Endianness: почему работает следующий код? - PullRequest
14 голосов
/ 03 июля 2011

Хотя я понимаю порядок байтов, мне немного неясно, как работает код ниже.Я предполагаю, что этот вопрос не столько о порядке байтов, а о том, как работают указатель char * и int, т.е. преобразование типов.Кроме того, имело бы какое-то значение, если бы переменная word была не short, а просто int?Спасибо!

#define BIG_ENDIAN 0
#define LITTLE_ENDIAN 1

int byteOrder() {
    short int word = 0x0001;
    char * byte = (char *) &word;
    return (byte[0] ? LITTLE_ENDIAN : BIG_ENDIAN);
}

Ответы [ 5 ]

17 голосов
/ 03 июля 2011

Короткое int состоит из двух байтов, в данном случае 0x00 и 0x01. В системе с прямым порядком байтов младший байт идет первым, поэтому в памяти он выглядит как 0x01, за которым следует 0x00. Большие порядковые системы, естественно, обращены вспять. Вот как выглядят указатели для коротких целых чисел в системе с прямым порядком байтов:

----------------------- ----------------------- 
|   0x01   |   0x00   | |          |          | 
----------------------- ----------------------- 
   &word                  &word+1

С другой стороны, указатели на символы всегда увеличиваются последовательно. Таким образом, взяв адрес первого байта целого числа и приведя его к указателю char *, вы можете увеличивать каждый байт целого числа в порядке следования памяти. Вот соответствующая диаграмма:

------------ ------------ ------------ ------------ 
|   0x01   | |   0x00   | |          | |          | 
------------ ------------ ------------ ------------ 
   &byte       &byte+1      &byte+2      &byte+3
7 голосов
/ 03 июля 2011

(char *)&word указывает на первый (самый низкий адрес) char (байт) из word. Если ваша система имеет младший порядок, это будет соответствовать 0x01; если это big-endian, это будет соответствовать 0x00.

И да, этот тест должен работать независимо от того, является ли word short, int или long (при условии, что они больше, чем char).

4 голосов
/ 03 июля 2011

Это милая маленькая программа.У вас есть слово, установленное в шестнадцатеричный литерал 1. Если у вас есть маленький порядковый номер, младший байт (0x01 в этом случае) будет в байте [0], когда вы приведете указатель на указатель на символ.и поэтому, если 0x01 находится со смещением 0, то вы знаете, что он был с прямым порядком байтов, в противном случае, если 0x00 находится со смещением 0, вы знаете, что наименее значащий байт был сохранен в старшей ячейке памяти (смещение 1).

Примечание: указатели всегда указывают на самый низкий адрес в памяти структуры слова / данных и т. д ...

2 голосов
/ 03 июля 2011

Это говорит вам о порядке байтов short. По крайней мере, на некоторых машинах, где short - это ровно два байта. Это не обязательно говорит вам о порядке байтов int или long, и, конечно, когда целочисленный тип больше двух байтов, выбор не является двоичным.

Реальный вопрос в том, почему вы хотели бы знать. Почти всегда проще и надежнее написать код, чтобы он не имел значения. (Существуют исключения, но они почти всегда включают код очень низкого уровня, который в любом случае будет работать только на одном конкретном оборудовании. И если вы достаточно хорошо знаете оборудование для написания такого рода кода, вы знаете порядок байтов.)

1 голос
/ 29 мая 2013

Уловка, которую я использую для запоминания порядка байтов, когда думаю о big-endian против little-endian, заключается в том, что «имена должны быть наоборот»:

  • Когда вы пишете число от руки, естественный способ сделать это - писать слева направо, начиная с самых значащих цифр и заканчивая наименьшими значащими цифрами. В вашем примере вы сначала пишете старший значащий байт (то есть 0), а затем младший значащий байт (то есть 1). Вот как работает big-endian. Когда он записывает данные в память (с увеличением адреса байта), он заканчивается младшими байтами - маленькими байтами. Таким образом, big-endian фактически заканчивается маленькими байтами.

  • То же самое для младшего байта: на самом деле он заканчивается самым старшим байтом, то есть «большими» байтами.

Ваш исходный код проверяет, является ли 1-й байт (т. Е. Байт [0]) самым старшим байтом (0), в этом случае это порядок старшего байта или порядок байтов с прямым порядком байтов.

...