2011-10-27 3 views
0

vxWorks 응용 프로그램을 Linux로 변환 중입니다. 나는 struct의 구성원을 액세스 할 때, 내 struct 멤버를 구축하기 위해 word's 레이아웃을 사용할 수 있도록uint32_t의 바이트 순서 결정

이전에, 나는 wordstructunion했다.

그러나 어떻게 생각했는지 기억하지 못하고 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의 레이아웃을 알아내는 것이 중요합니다.

+3

이렇게해서는 안됩니다. 'uint32_t foobar = 0x00ff00ff; if ((char *) foobar) [0] == 0xff)/* 하나의 엔도 니어 */ else/* 다른 * /' – Alex

+0

무엇이 문제입니까? – anatolyg

+0

http://stackoverflow.com/questions/6359629/union-hack-for-endian-testing-and-byte-swapping에 대해 질문합니까? – Gnawme

답변

1

귀하의 의견에서 다른 answer으로 회원의 union 회원이 fields.bytesN 회원에게 표시되도록하십시오. 이를 달성하려면 머신 엔디안을 감지 한 후 field 비트 필드를 적절히 배치하거나 빅 엔디안 용과 리틀 엔디안 용으로 2 가지 구조를 생성하는 사전 빌드 프로세스가 있어야합니다. 물론

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; 

    } 
} 

, 당신은 단지 당신이 보여준 원래의 레이아웃 대신 fieldsLE의 레이아웃을 사용하여 포트 리틀 엔디안을 지원합니다.

+0

순서가 바뀌 었습니다 –

+0

하지만 bytesN을 31로, 23을 공백으로, byteA를 1로 변경해야했습니다. –

3

int에 0x01 값이 들어있는 포인터를 가져 와서 char *으로 전송하면 알 수 있습니다. 첫 번째 값이 0이면 시스템은 빅 엔디안이고 그렇지 않으면 리틀 엔디안입니다.

#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); 
} 

내가 리눅스, 솔라리스, OS X,와 FreeBSD에서이 방법을 사용했습니다 : 여기

은 예입니다.

+0

예,이 작업을 수행하는 방법을 알고 있습니다. 그러나 'word'에 40이라는 숫자가 포함되어 있다면 그 숫자를 bytesN으로 나타내야합니다. blank 또는 bytesA가 아닙니다. 이것이 레이아웃이 중요한 이유입니다. uint32_t가 구체적으로 배치되는 방법. –

+0

@ 0A0D 이걸 원하니? '상태 x; x.word = 40; printf ("% d", x.fields.bytesN);' – anatolyg

+1

문제는 'Status.word'에 접근 할 때 바이트에 접근하는 순서를 뒤집지 않는다는 것입니다. Big Endian (하드웨어는 B3, B2, B1, B0으로 저장되지만 Little Endian에는 정수가 B0, B1, B2, B3으로 저장됩니다.) 이것은 빅 엔디안 하드웨어에서 (on (Status. 리틀 엔디안 하드웨어에서는 ((Status .fields.byteN == 15) && (Status.word == 0x0F000000)) '빅 엔디안에서 전환 할 때 byteN == 15) && (Status.word == 0x0F) 플랫폼 루어는'Status.fields'의 비트 순서를 반대로하거나'Status.word'에 접근하기 위해 사용하는 비트 순서를 반대로 할 필요가 있습니다. –