2011-10-27 13 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に移植する際に、いくつかのエンディアンの問題が発生しました。だから、Linux上でuint32_tのレイアウトを考え出すことは重要です。

+3

このようなものではありませんか? 'uint32_t foobar = 0x00ff00ff; if(((char *)foobar)[0] == 0xff)/ *エンディアン1つ*/ else/* other */' – Alex

+0

何が問題なのですか? – anatolyg

+0

http://stackoverflow.com/questions/6359629/union-hack-for-endian-testing-and-byte-swappingについて質問していますか? – Gnawme

答えて

1

お客様のご意見からanswerwordメンバーの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、blankを23、byteAを1に変更しなければなりませんでした。 –

3

値0x01を含むintへのポインタをとり、それを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にします。それがレイアウトが重要な理由です。 uint32_tが具体的にどのようにレイアウトされているか。 –

+0

@ 0A0Dだからあなたはこれをしたいですか? 'ステータスx; x.word = 40; printf( "%d"、x.fields.bytesN); ' – anatolyg

+1

あなたの問題は、あなたが' Status.word'にアクセスする際にバイトにアクセスする順序を逆にしていないことです。ビッグエンディアン(ハードウェアの整数はB3、B2、B1、B0として保存されますが、リトルエンディアンでは整数がB0、B1、B2、B3として格納されます)。リトルエンディアンハードウェア '((Status .fields.byteN == 15)&&(Status.word == 0x0F000000))では、ビッグエンディアンからの切り替え時には、バイトN == 15)&&(Status.word == 0x0F)プラットフォームのrouは、 'Status.fields'のビット順を逆にするか、' Status.word'にアクセスするために使用するビット順を逆にする必要があります。 –

関連する問題