uint32_tのバイト順序を決定する

私はvxWorksアプリケーションをLinuxに変換しています。

以前は、 struct のメンバーにアクセスするときに、構造体のメンバーにアクセスするために word word レイアウトを使用して、 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に移植する際にいくつかのエンディアンの問題に遭遇しました。だから、Linux上で uint32_t のレイアウトを理解することは重要です。

0
質問は何ですか?
追加された 著者 anatolyg,
このような何かがトリックをしてはいけないのですか? uint32_t foobar = 0x00ff00ff; if((char *)foobar)[0] == 0xff)/ * endianess */else/*他の*/
追加された 著者 Alex,

2 答え

値0x01を含む int へのポインタを取り出し、それを char * にキャストすることで分かります。最初の値がゼロに等しい場合、システムはビッグエンディアンです。そうでない場合は、リトルエンディアンです。

次に例を示します。

#include 
#include 

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上でこのメソッドを使用しました。

3
追加された
@ 0A0Dだからあなたはこれをしたいですか? ステータスx; x.word = 40; printf( "%d"、x.fields.bytesN);
追加された 著者 anatolyg,
あなたの問題は、 Status.word にアクセスする際にバイトにアクセスする順序を逆にしていないことです。ビッグエンディアン(ハードウェアの整数はB3、B2、B1、B0として保存されますが、リトルエンディアンには整数がB0、B1、B2、B3として格納されます。リトルエンディアンのハードウェア((Status .fields.byteN == 15)&&(Status.word == 0x0F000000))に対して、fields.byteN == 15)&&(Status.word == 0x0F))ビッグエンディアンプラットフォームから切り替えるときは、 Status.fields のビット順序を逆にするか、 Status.word にアクセスするために使用するビット順序を逆にする必要があります。
追加された 著者 David M. Syzdek,
@anatolygあなたはあなたの質問を洗練する必要がありますバイトオーダーを見つけることができない場合、何をしたいですか?
追加された 著者 Alex,
はい、私はこれを行う方法を知っています。しかし、 word に40という数字が含まれている場合は、その番号を空白やbytesAではなくbytesNで指定します。それがレイアウトが重要な理由です。 uint32_tが具体的にどのようにレイアウトされているか。
追加された 著者 user195488,

あなたのコメントから他の答えまで、あなたは fields.bytesN メンバーに表示されるように union word メンバーに埋め込まれています。これを実現するには、マシンエンディアンを検出した後にフィールドビットフィールドを適切にレイアウトするか、ビッグエンディアン用とリトルエンディアン用の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 のレイアウトを使用してください。

1
追加された
注文を元に戻しました。
追加された 著者 user195488,
バイトNを31、空白を23、バイトAを1に変更しなければなりませんでした。
追加された 著者 user195488,