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

(Этот вопрос возник из-за объяснения деталей CHAR_BIT, sizeof и порядка следования байтов кому-то вчера. Это совершенно гипотетически.)

Допустим, я на платформе, где CHAR_BIT равен 32, поэтому sizeof(char) == sizeof(short) == sizeof(int) == sizeof(long). Я считаю, что это все еще среда, соответствующая стандартам.

Обычный способ определения порядка байтов во время выполнения (потому что нет надежного способа сделать это во время компиляции) означает создать union { int i, char c[sizeof(int)] } x; x.i = 1 и посмотреть, установлены ли x.c[0] или x.c[sizeof(int)-1].

Но это не работает на этой платформе, так как я получаю char[1].

Есть ли способ определить, является ли такая платформа обратным порядком байтов или прямым порядком байтов во время выполнения? Очевидно, внутри этой гипотетической системы это не имеет значения, но можно представить, что она записывает в файл или какую-то область памяти, которую другая машина читает и реконструирует в соответствии со своей (более разумной) моделью памяти.


person Community    schedule 17.01.2011    source источник
comment
вы можете попробовать макрос AC_C_BIGENDIAN autoconf, чтобы сделать это во время компиляции, он довольно надежен, прибегая к grep на тестовом двоичном файле, если он не может запустить код напрямую.   -  person Hasturkun    schedule 17.01.2011


Ответы (8)


Концепция порядка следования байтов имеет смысл только для скалярных типов, представленных несколькими байтами. По определению char является однобайтовым, поэтому любой целочисленный тип, имеющий тот же размер, что и char, не имеет порядка следования байтов.

Также имейте в виду, что порядок следования байтов может быть разным для разных типов: например, PDP-11 представляет собой 16-битную архитектуру с прямым порядком байтов, а 32-битные целые числа строятся из двух 16-битных значений с прямым порядком байтов, что в итоге приводит к смешанному порядку байтов. порядок байтов

person Christoph    schedule 17.01.2011
comment
Ваш комментарий к ответу Мартина кажется мне лучшим объяснением. Порядок байтов в этой системе имеет значение только тогда, когда нам нужно перевести его в другую систему — каким бы ни был этот шаг перевода, он не может быть написан в той же среде C — следовательно, вопрос не имеет смысла для этой платформы, даже если физически байты/биты имеют некоторый базовый порядок, который может проверить уровень перевода. - person ; 17.01.2011
comment
порядок следования байтов (он же порядок байтов) — это понятие, не зависящее от понятия октетов — исторически байты бывают разных размеров (4-битный BCD, 6-битный графический набор, 16-битный DSP), и до сих пор существуют устройства специального назначения. с CHAR_BIT != 8; пока существуют многобайтовые скалярные типы, порядок следования байтов является четко определенной концепцией; сериализация на 8-битные устройства не имеет значения с этой точки зрения - person Christoph; 17.01.2011

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

Я вижу для вас три возможности:

  • Если ограничение задается только компилятором C и технически платформа имеет несколько меньших типов данных, вы можете использовать ассемблер для определения порядка следования байтов.

  • Если платформа поддерживает двойной тип данных, вы можете использовать его для определения порядка следования байтов, поскольку он всегда имеет ширину 64 бита.

  • Также вы можете записать данные в файл, как вы предложили, а затем прочитать обратно. Просто напишите два символа (файл в двоичном режиме), переместите указатель файла в позицию 1 и прочитайте символ.

person Al Kepp    schedule 17.01.2011
comment
››Также вы можете записать данные в файл, как вы предложили, а затем прочитать обратно. ... не уверен, как это будет реализовано, если у системы нет средств для адресации чего-либо ниже 32 бит. Мое понимание такой системы заключается в том, что один байт на самом деле составляет 32 бита, а позиция файла 1 (с нуля) - это та же позиция файла 4 (где байты состоят из 8 бит) - person bestsss; 17.01.2011
comment
в общем, не существует общеплатформенной концепции порядка следования байтов: если вы используете значение double для проверки порядка следования байтов, вы получите порядок следования байтов этого типа и ничего больше; Кроме того, я не понимаю вашего алгоритма определения порядка следования байтов путем записи на диск: стандарт-io ориентирован на байты, и вы не получите из него больше информации, чем путем преобразования в char * - person Christoph; 17.01.2011
comment
Хотелось бы посмотреть, как сокеты TCP/IP будут реализованы на такой 32-битной платформе. - person Al Kepp; 17.01.2011
comment
Также запись в файл может быть реализована как угодно, т.е. биты этого символа/целого числа могут быть сохранены иначе, чем порядок байтов памяти. - person bestsss; 17.01.2011
comment
@Al: Мое первое предположение было бы TCP / IP, но тогда результатом был бы просто сетевой формат для исходящих битов. Нет никакой проблемы в том, чтобы подкрутить сетевую карту, ничего не говоря о модели памяти. Я склонен сказать, что определение порядка следования байтов невозможно. - person bestsss; 17.01.2011
comment
Кристоф: Если у вас есть поток двоичных файлов, вы записываете в него целые блоки памяти, а не байт за байтом, потому что операционная система делает это в больших блоках памяти. Запись байт за байтом привела бы к дополнительным вычислительным затратам. Вот почему я ожидаю, что его можно использовать для обнаружения порядка байтов. Я просто ожидаю, не могу быть уверен, так как это слишком гипотетично. - person Al Kepp; 17.01.2011
comment
@Al: Кто знает, существует ли вообще TCP/IP на этой платформе? Это не предусмотрено стандартом C. - person Martin B; 17.01.2011
comment
@Al даже запись целых фрагментов памяти не позволяет адресовать 8 бит, что вы, по сути, делаете, перемещая указатель в позицию 1. - person bestsss; 17.01.2011
comment
@bestsss: когда ваш файл записан на диск, вы можете переместить указатель файла в позицию 1. Файлы состоят из реальных 8-битных байтов, они не состоят из переменных языка C. Интересным моментом является то, что файлы могут быть единственным местом, где вы можете увидеть порядок байтов в этой гипотетической среде. Может быть, порядок байтов файловой системы просто искусственно построен, как вы писали ранее, путем реализации дисковых операций, но все же это порядок байтов нашей гипотетической системы. О, может быть, нам лучше прекратить эту дискуссию. Я теряюсь в нем. ;-) - person Al Kepp; 17.01.2011

Я полагаю, что вопрос сводится к следующему: является ли порядок следования байтов значимой концепцией на этой платформе, то есть оказывает ли он заметное влияние на поведение программы?

Если это не так, то порядок следования байтов (т. е. порядок, в котором отдельные байты, составляющие 32-битное число, хранятся в памяти) — это просто деталь реализации, которую вы не можете обнаружить, но которая и не должна вас беспокоить.

Если порядок следования байтов оказывает заметное влияние на поведение определенного аспекта языка... что ж, тогда создайте тест, основанный на этом поведении. Вот некоторые примеры:

  • Как работает система адресации на платформе? Если вы увеличиваете адрес на единицу, скольким битам это соответствует? Если ответ состоит из восьми битов и система позволяет вам читать с адресов, не кратных четырем, то вы можете переместить указатель вперед на один байт (через обход к intptr_t) и таким образом проверить порядок следования байтов. (Да, это поведение, определяемое реализацией, но то же самое относится и к использованию объединения для проверки порядка следования байтов, а также всей концепции порядка следования байтов в целом.) Однако если наименьшая адресуемая единица памяти составляет 32 байта, то вы можете t проверить порядок байтов таким образом.

  • Есть ли на платформе 64-битный тип данных (long long)? Затем вы можете создать объединение long long и двух int и построить на его основе свой тест на порядок следования байтов.

person Martin B    schedule 17.01.2011
comment
Конечно, вы можете обнаружить это. Установите 2-байтовое целое число в 1 и посмотрите, какой из байтов отличен от нуля. - person David Heffernan; 17.01.2011
comment
››Допустим, я работаю на платформе, где CHAR_BIT равен 32, поэтому sizeof(char) == sizeof(short) == sizeof(int) == sizeof(long). Я считаю, что это все еще среда, совместимая со стандартами. ‹‹ байт/символ в точности равен целому числу. - person bestsss; 17.01.2011
comment
@David Heffernan› вы не видите ни байта. В этой среде C нет байтов. :-) - person Al Kepp; 17.01.2011
comment
@Al Kepp: конечно, есть байты - просто все целые типы однобайтовые ... - person Christoph; 17.01.2011
comment
Мне кажется, что порядок следования байтов должен быть значимой концепцией на каком-то уровне, если эта архитектура когда-либо собирается отправлять информацию по сети на другой компьютер с байтами стандартного размера. Мне любопытно, могла ли программа в этой системе выбирать, отправлять ли (то, что на другой компьютер) прямой или прямой порядок байтов, или компьютеру-получателю нужно будет выполнить перевод. - person ; 17.01.2011
comment
@Joe: архитектура с 32-битными байтами не может выполнять необходимые преобразования для передачи 8-битного провода в C; ему нужна внешняя единица перевода, и порядок следования байтов, который вы получаете из этого, на самом деле не является свойством среды выполнения C. - person Christoph; 17.01.2011

Битовые поля структуры должны корректно работать на любой платформе, даже на этой:

union {
   int i;
   struct {
       int b1 : 8;
       int b2 : 8;
       int b3 : 8;
       int b4 : 8;
   } s;
} u;

u.i = 1;
if (u.s.b1 != 0)
   ....
person SoapBox    schedule 17.01.2011
comment
Не будет работать, потому что компиляторы (по крайней мере те, с которыми я работал) используют байты для битовых полей в порядке памяти. Таким образом, как для платформы с прямым порядком байтов, так и для платформы с обратным порядком байтов u.b1 == 1 будет верным. (Это решение не будет работать даже с битовыми полями в 1 бит.) - person Didier Trosset; 17.01.2011
comment
Порядок битов зависит от машины IIRC, поэтому я не совсем уверен, что это сработает. - person Hasturkun; 17.01.2011

Вопрос не предлагает достаточно информации, но с тем, что он предлагает, я бы сказал: невозможно.

person bestsss    schedule 17.01.2011

htonl должно работать:

if(htonl(1)==1) {
   /* network order (big-endian) */
} else {
   /* little-endian */
}

(Я не вижу никаких причин не реализовывать htonl и друзей обычным образом, даже для этой надоедливой гипотетической системы — хотя я не уверен, насколько полезной они окажутся на практике.)

person Community    schedule 18.01.2011

Вы можете сдвинуть рассматриваемую переменную и посмотреть, с какого конца сдвигается 1.

person Sparr    schedule 26.03.2012

Если ваш код зависит от того, является ли архитектура BE или LE, тогда ваш код должен иметь безопасность и не компилироваться для неизвестной платформы. Некоторые #if ! defined(ARCH_IS_LE) && ! defined(ARCH_IS_BE) \ #error unknown architecture должны делать.

person wilx    schedule 17.01.2011