C Макроопределение для определения машины с прямым или прямым порядком байтов? - PullRequest
101 голосов
/ 20 января 2010

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

unsigned char test_endian( void )
{
    int test_var = 1;
    unsigned char test_endian* = (unsigned char*)&test_var;

    return (test_endian[0] == NULL);
}

Ответы [ 18 ]

5 голосов
/ 20 января 2010

Несмотря на то, что нет переносимого #define или чего-либо, на что можно было бы положиться, платформы предоставляют стандартные функции для преобразования в и из вашего порядкового номера «хоста».

Как правило, вы делаете хранилище - на диск или сеть - используя 'endian сети', который является BIG endian, и локальные вычисления, используя endian хоста (который на x86 равен LITTLE обратный порядок байт). Вы используете htons() и ntohs() и друзей, чтобы конвертировать между ними.

3 голосов
/ 02 ноября 2016

Не забывайте, что порядковый номер не является целой историей - размер char может быть не 8 бит (например, DSP), отрицание дополнения до двух не гарантируется (например, Cray), может потребоваться строгое выравнивание (например, SPARC Кроме того, ARM переходит в Middle-Endian , когда не выровнены), и т. д., и т. д.

Возможно, лучше выбрать конкретную архитектуру процессора .

Например:

#if defined(__i386__) || defined(_M_IX86) || defined(_M_IX64)
  #define USE_LITTLE_ENDIAN_IMPL
#endif

void my_func()
{
#ifdef USE_LITTLE_ENDIAN_IMPL
  // Intel x86-optimized, LE implementation
#else
  // slow but safe implementation
#endif
}

Обратите внимание, что это решение, к сожалению, также не является сверхпортативным, так как оно зависит от определений, специфичных для компилятора (стандарта нет, но вот хорошая компиляция таких определений).

3 голосов
/ 20 января 2010

Попробуйте это:

#include<stdio.h>        
int x=1;
#define TEST (*(char*)&(x)==1)?printf("little endian"):printf("Big endian")
int main()
{

   TEST;
}
3 голосов
/ 13 февраля 2012
#include <stdint.h>
#define IS_LITTLE_ENDIAN (*(uint16_t*)"\0\1">>8)
#define IS_BIG_ENDIAN (*(uint16_t*)"\1\0">>8)
1 голос
/ 12 января 2019

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

Для , например , в ARM Cortex-M3 реализованная последовательность будет отражаться в бите состояния AIRCR.ENDIANNESS, и компилятор не может знать это значение во время компиляции.

Вывод компиляции для некоторых ответов, предложенных здесь:

https://godbolt.org/z/GJGNE2 для это ответ,

https://godbolt.org/z/Yv-pyJ для этого ответа и т. Д.

Для ее решения вам понадобится квалификатор volatile. Ответ Yogeesh H T является наиболее близким для сегодняшнего использования в реальной жизни, но поскольку Christoph предлагает более всеобъемлющее решение, небольшое исправление его ответа сделает ответ завершенным, просто добавьте volatile к профсоюзная декларация: static const volatile union.

Это обеспечит сохранение и чтение из памяти, что необходимо для определения порядка байтов.

0 голосов
/ 07 января 2017

C Код для проверки, является ли система прямым или старшим индийским.

int i = 7;
char* pc = (char*)(&i);
if (pc[0] == '\x7') // aliasing through char is ok
    puts("This system is little-endian");
else
    puts("This system is big-endian");
0 голосов
/ 13 апреля 2016

Мой ответ не такой, как просили, но действительно просто найти , если ваша система имеет прямой или прямой порядок байтов?

Код:

#include<stdio.h>

int main()
{
  int a = 1;
  char *b;

  b = (char *)&a;
  if (*b)
    printf("Little Endian\n");
  else
    printf("Big Endian\n");
}
0 голосов
/ 01 декабря 2015

Макрос, чтобы найти endiannes

#define ENDIANNES() ((1 && 1 == 0) ? printf("Big-Endian"):printf("Little-Endian"))

или

#include <stdio.h>

#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}

int main(void) 
{
       ENDIAN();
       return 0;
}
...