Определить макросы на основе порядкового номера машины - PullRequest
0 голосов
/ 11 апреля 2019

Я хочу определить переменные в структуре на основе порядкового номера машины. Это то, что я пытался

#define IS_BIG_ENDIAN (!(union { uint16_t u16; unsigned char c; }){ .u16 = 1 }.c)
//#define IS_BIG_ENDIAN (!*(unsigned char *)&(uint16_t){1})
struct A {
    #if IS_BIG_ENDIAN
    char a:4;
    char b:4;
    #else
    char b:4;
    char a:4;
    #endif
}

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

Ответы [ 4 ]

2 голосов
/ 11 апреля 2019

С https://sourceforge.net/p/predef/wiki/Endianness/

У вас нет стандартного способа его получения.

, но пользовательские заголовки <sys/param.h> или <endian.h> могут предоставлять MACRO, например:

Type                            Macro           Value
Big endian                      __BYTE_ORDER    __BIG_ENDIAN
Little endian                   __BYTE_ORDER    __LITTLE_ENDIAN
Little endian (word-swapped)    __BYTE_ORDER    __PDP_ENDIAN
1 голос
/ 11 апреля 2019

Этот тест не может работать для директивы if препроцессора.

Предполагается, что в следующем C ++ 20 будет std::endian.Его можно использовать без предварительного процессора.

static_assert(std::endian::native == std::endian::big
           || std::endian::native == std::endian::little);

struct ABig {
    char a:4;
    char b:4;
};

struct ALit {
    char b:4;
    char a:4;
};

using A = std::conditional_t<std::endian::native == std::endian::big, ABig, ALit>;

До C ++ 20 стандартного способа получения порядкового номера не существует.

Переносимое решение заключается в использовании предопределенныхмакросы для обнаружения системы.Некоторые системы имеют прямой порядок байтов (Windows), в то время как другие предоставляют заголовок с определениями макросов (<endian.h> в Linux, <sys/endian.h> в BSD и т. Д.), А другие могут отличаться другим способом.Компилятор GCC предоставляет макросы:

__BYTE_ORDER__
__ORDER_LITTLE_ENDIAN__
__ORDER_BIG_ENDIAN__
__ORDER_PDP_ENDIAN__

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

Лучше не полагаться на представление битовых полей.

1 голос
/ 11 апреля 2019

Дождитесь C ++ 20 (или используйте экспериментальные функции вашего компилятора), и вы сможете использовать стандарт C ++ std :: endian для этого:

Указывает порядковый номер всех скалярных типов:

Если все скалярные типы с прямым порядком байтов, std :: endian :: native равно std :: endian :: little Если все скалярные типы являются старшими, std :: endian :: native равно std :: endian :: big

0 голосов
/ 12 апреля 2019

Спасибо @ Jarod42, следующий код работает для меня

#define IS_BIG_ENDIAN !(__BYTE_ORDER__- __BIG_ENDIAN)
struct A {
    #if IS_BIG_ENDIAN
    char a:4;
    char b:4;
    #else
    char b:4;
    char a:4;
    #endif
};
...