2011-10-27 3 views
0

Я конвертирую приложение vxWorks в Linux.Определить порядок байтов uint32_t

Раньше я был union с word и struct так, что, когда я получил доступ к членам struct, я мог бы использовать word's расположение, чтобы построить мои struct членов.

Однако я не помню, как я это понял, и он работает с полем vxWorks. На моем случае VxWorks, макет:

typedef union Status 
{ 
    struct fields 
    { 
     uint32_t byteA : 1; // <31> 
     uint32_t blank : 23; // <30:8> 
     uint32_t bytesN : 8; // <7:0> 
    } fields; 

    uint32_t word; 
} 

Я уже столкнулся с некоторыми вопросами обратным порядком байтов при переносе с VxWorks на Linux. Таким образом, важно выяснить расположение uint32_t на linux.

+3

не должно быть что-то вроде этого делать трюк? 'uint32_t foobar = 0x00ff00ff; if (((char *) foobar) [0] == 0xff)/* one endianess */ else/* другой */' – Alex

+0

В чем вопрос? – anatolyg

+0

Вы спрашиваете о http://stackoverflow.com/questions/6359629/union-hack-for-endian-testing-and-byte-swapping? – Gnawme

ответ

1

Ваш комментарий к другой answer, вы хотите, что бы ни чучела в word члена union появляться в fields.bytesN члена. Чтобы достичь этого, вы должны либо иметь какой-то процесс предварительной сборки, который соответствующим образом определяет поля бит field после обнаружения консистенции машины, либо создает две структуры: одну для большого конца, а другую для маленького конца.

typedef union Status 
{ 
    struct fieldsBE 
    { 
     uint32_t byteA : 1; // <31> 
     uint32_t blank : 23; // <30:8> 
     uint32_t bytesN : 8; // <7:0> 
    } fieldsBE; 

    struct fieldsLE 
    { 
     uint32_t bytesN : 8; // <7:0> 
     uint32_t blank : 23; // <30:8> 
     uint32_t byteA : 1; // <31> 
    } fieldsLE; 

    uint32_t word; 
}; 

int main() 
{ 
    bool isBigEndian = DetectEndianness(); // returns true if big endian 

    Status status; 

    status.word = 40; 

    if(isBigEndian) { 
    uint8_t bytesN = status.fieldsBE.bytesN; 

    } else { 
    uint8_t bytesN = status.fieldsLE.bytesN; 

    } 
} 

Конечно, если вы хотите, чтобы поддержать Little Endian в вашем порту использовать макет fieldsLE вместо оригинального макета вы показали.

+0

Обратный порядок выполнен. –

+0

, но мне пришлось сменить байтыN на 31, пробел до 23 и байтыA на 1. –

3

Вы можете указать, указав указатель на int, содержащий значение 0x01, и отбрасывая его на char *. Если первое значение равно нулю, то система является большой энтикой, в противном случае она малозначительна.

Вот пример:

#include <inttypes.h> 
#include <stdio.h> 

int main(void) 
{ 
    uint32_t val = 0x01; 
    char  * buff = (char *)&val; 

    if (buff[0] == 0) 
    { 
     printf("Big endian\n"); 
    } else { 
     printf("Little endian\n"); 
    }; 

    return(0); 
} 

Я использовал этот метод на Linux, Solaris, OS X и FreeBSD.

+0

Да, я знаю, как это сделать. Но если 'word' содержит число 40, я хочу, чтобы это число в байтахN, а не в пустом или bytesA. Вот почему макет важен. Как конкретно выкладывается uint32_t. –

+0

@ 0A0D Итак, вы хотите это сделать? 'Статус x; x.word = 40; printf ("% d", x.fields.bytesN); ' – anatolyg

+1

Ваша проблема в том, что вы не изменяете порядок, в котором вы получаете доступ к байтам при доступе к' Status.word'. В Big Endian (аппаратное обеспечение целое число хранится как B3, B2, B1, B0, однако на маленьком Endian целое число сохраняется как B0, B1, B2, B3. Это означает, что на аппарате большого конца ((Status .fields. byteN == 15) && (Status.word == 0x0F)) 'while on little endian hardware' ((Status .fields.byteN == 15) && (Status.word == 0x0F000000)) 'При переключении с большого конца платформа rou либо должна отменить порядок бит 'Status.fields', либо изменить порядок бит, используемый для доступа к' Status.word' –

Смежные вопросы