Есть ли однострочное определение макроса для определения порядка байтов машины. Я использую следующий код, но преобразовывать его в макрос было бы слишком долго.
unsigned char test_endian( void )
{
int test_var = 1;
unsigned char *test_endian = (unsigned char*)&test_var;
return (test_endian[0] == 0);
}
c
architecture
macros
endianness
манав мн
источник
источник
0
вместо этогоNULL
в своем последнем тесте и заменить один изtest_endian
объектов на что-то другое :-).#if
директивы.Ответы:
Код, поддерживающий произвольный порядок байтов, готовый для помещения в файл с именем
order32.h
:Вы можете проверить системы с прямым порядком байтов через
источник
char
? Лучше использоватьuint8_t
и потерпеть неудачу, если этот тип недоступен (что можно проверить#if UINT8_MAX
). Обратите внимание, чтоCHAR_BIT
это не зависит отuint8_t
.O32_HONEYWELL_ENDIAN = 0x02030001ul /* Honeywell 316 */
Если у вас есть компилятор, поддерживающий составные литералы C99:
или:
В общем, вы должны попытаться написать код, который не зависит от порядка байтов хост-платформы.
Пример независимой от хоста реализации
ntohl()
:источник
ntohl
это способом, который не зависит от порядка байтов хост-платформы.Не существует стандарта, но во многих системах, в том числе
<endian.h>
, вы найдете несколько определений, которые нужно искать.источник
#if __BYTE_ORDER == __LITTLE_ENDIAN
и#elif __BYTE_ORDER == __BIG_ENDIAN
. И сгенерируйте#error
иначе.<endian.h>
недоступен в Windowsendian.h
если не определено__APPLE__
или_WIN32
.#if BYTE_ORDER == LITTLE_ENDIAN
(илиBIG_ENDIAN
) без символов подчеркивания перед именами._BYTE_ORDER
только для системных заголовков.__BYTE_ORDER
не существует.Чтобы определить порядок байтов во время выполнения, вы должны иметь возможность обращаться к памяти. Если вы придерживаетесь стандарта C, для объявления переменной в памяти требуется оператор, а для возврата значения требуется выражение. Я не знаю, как это сделать в одном макросе - вот почему у gcc есть расширения :-)
Если вы хотите иметь файл .h, вы можете определить
а затем вы можете использовать
ENDIANNESS
макрос по своему усмотрению.источник
Если вы хотите полагаться только на препроцессор, вам нужно выяснить список предопределенных символов. Арифметика препроцессора не имеет понятия адресации.
GCC на Mac определяет
__LITTLE_ENDIAN__
или__BIG_ENDIAN__
Затем вы можете добавить дополнительные условные директивы препроцессора на основе определения платформы, например,
#ifdef _WIN32
и т. Д.источник
#define __BIG_ENDIAN__ 1
и#define _BIG_ENDIAN 1
.#define __LITTLE_ENDIAN__ 1
. Этот макрос кажется функцией clang, а не функцией gcc. Наgcc
некоторых компьютерах Mac команда не gcc, а clang.Я считаю, что это то, о чем просили. Я тестировал это только на машине с прямым порядком байтов под msvc. Кто-нибудь, пожалуйста, подтвердите на машине с прямым порядком байтов.
В качестве побочного примечания (для конкретного компилятора) с агрессивным компилятором вы можете использовать оптимизацию с «устранением мертвого кода» для достижения того же эффекта, что и во время компиляции,
#if
например:Выше , основано на том , что компилятор распознает значения постоянная во время компиляции, полностью удаляет код внутри
if (false) { ... }
и заменяет код какif (true) { foo(); }
сfoo();
наихудшим сценарием: компилятор не делает оптимизацию, вы все равно получите правильный код , но немного медленнее.источник
'ABCD'
?clang -Wpedantic -Werror -Wall -ansi foo.c
ошибкой. (Clang и это определенно:-Wfour-char-constants -Werror
)Если вы ищете тест на время компиляции и используете gcc, вы можете:
См. Документацию gcc для получения дополнительной информации.
источник
__BYTE_ORDER__
доступно, начиная с GCC 4.6Фактически вы можете получить доступ к памяти временного объекта, используя составной литерал (C99):
Какой GCC будет оценивать во время компиляции.
источник
#if __STDC_VERSION__ >= 199901L
.«Сетевая библиотека C» предлагает функции для обработки порядка байтов. А именно htons (), htonl (), ntohs () и ntohl () ... где n - это «сеть» (т. Е. Обратный порядок байтов), а h - «хост» (т. Е. Порядок байтов машины, на которой выполняется код).
Эти очевидные «функции» (обычно) определяются как макросы [см. <Netinet / in.h>], поэтому их использование не требует дополнительных затрат времени выполнения.
Следующие макросы используют эти «функции» для оценки порядка байтов.
К тому же:
Единственный раз, когда мне нужно знать порядок байтов системы, - это когда я записываю переменную [в файл / другой], которая может быть прочитана другой системой с неизвестным порядком байтов (для кросс-платформенной совместимости ) ... В таких случаях вы можете предпочесть напрямую использовать функции endian:
источник
Используйте встроенную функцию, а не макрос. Кроме того, вам нужно что-то хранить в памяти, что является не очень приятным побочным эффектом макроса.
Вы можете преобразовать его в короткий макрос, используя статическую или глобальную переменную, например:
источник
s_endianess
для начала не установлено значение 1?Хотя нет переносимого #define или чего-то, на что можно положиться, платформы предоставляют стандартные функции для преобразования в исходный код вашего «хоста» и обратно.
Как правило, вы выполняете хранение - на диск или в сеть - с использованием метода обратного порядка байтов в сети, который является BIG endian, и локальных вычислений с использованием порядка байтов хоста (что на x86 является LITTLE endian). Вы используете
htons()
иntohs()
и друзей для преобразования между ними.источник
источник
Не забывайте, что порядок байтов - это еще не все - размер
char
может быть не 8 бит (например, DSP), отрицание дополнения до двух не гарантируется (например, Cray), может потребоваться строгое выравнивание (например, SPARC, также ARM переходит в середину -endian без выравнивания ) и т. д. и т. д.Возможно, было бы лучше использовать конкретную архитектуру ЦП .
Например:
Обратите внимание, что это решение также не является ультрапортативным, к сожалению, поскольку оно зависит от определений, специфичных для компилятора (стандарта нет, но вот хорошая подборка таких определений).
источник
Попробуй это:
источник
Обратите внимание, что большинство ответов здесь не переносимы, так как сегодня компиляторы будут оценивать эти ответы во время компиляции (в зависимости от оптимизации) и возвращать определенное значение на основе определенного порядка байтов, в то время как фактический порядок байтов машины может отличаться. Значения, на которых проверяется порядок байтов, никогда не попадут в системную память, поэтому реальный исполняемый код вернет тот же результат, независимо от фактического порядка байтов.
К примеру , в ARM Cortex-M3 внедренная порядок байт будет отражать в битовом статус AIRCR.ENDIANNESS и компилятор не может знать это значение во время компиляции.
Вывод компиляции для некоторых из предложенных здесь ответов:
https://godbolt.org/z/GJGNE2 для этого ответа,
https://godbolt.org/z/Yv-pyJ для этого ответа и так далее.
Для ее решения вам нужно будет использовать
volatile
квалификатор.Yogeesh H T
«S ответ ближе всего один для сегодняшнего реального использования жизни, но так какChristoph
предполагает более комплексное решение, небольшое исправление к его ответу будет сделать ответ полным, просто добавьтеvolatile
к объявлению союза:static const volatile union
.Это обеспечит сохранение и чтение из памяти, что необходимо для определения порядка байтов.
источник
Если вы сбросите препроцессор #defines
Обычно вы можете найти то, что вам поможет. С логикой времени компиляции.
Однако разные компиляторы могут иметь разные определения.
источник
Мой ответ не такой, как спросили, но действительно ли просто определить, является ли ваша система прямым или прямым порядком байтов?
Код:
источник
C Код для проверки того, является ли система прямым или обратным порядком байтов.
источник
Макрос для поиска порядка байтов
или
источник