2012-01-19 17 views
3

をchar型:長いの連合と私は8ビットプロセッサ用のコードに次のような場合は[]、バイト順

typedef union 
{ 
unsigned long longn ; 
unsigned char chars[4]; 
} longbytes; 

longbytes.chars[0]は常にlongbytes.longnの最下位バイトになるだろうか、それが依存しませんエンディアン/コンパイラ/プラットフォーム/ターゲット/運などで?私は準拠したコードの逆アセンブリを見てきましたが、それは私の特定のケースでどのようになっているのですが、このコードが移植可能かどうかは不思議です。

答えて

7

いくつかの理由があります。

  • あなたは最下位バイトのアドレス指定chars[0]に数えることができないので、それは、バイトが最初に書かれているご使用のプラットフォーム(またはコンパイラ)が施行エンディアンに依存
  • unsigned longはそうプラットフォームに応じて、あなたもlong完全(またはのsizeof(long)が4、その後小さくなる可能性があり、あなたがさらに読み、それが8ビットのためにそうだ得られない可能性があります、正確に限り4として文字であることが保証されていません少なくともプロセッサー。
  • あなたが書いた別の共用体メンバを読むことは一般的に移植性がありません。実装定義の動作です。この理由は、基本的に2つの他の問題の組み合わせです。

このコードはすべて移植性がありません。

+0

、6.5.2.3を、脚注95は、」読み込みではありませんオブジェクトに値を格納するために最後に使用されたメンバと同じですが、値のオブジェクト表現の適切な部分は、6.2.6で説明されているように新しい型のオブジェクト表現として再解釈されますこれはトラップ表現かもしれない」だから、今日は準定義されています。 –

+0

私は、この規格では、 'unsigned char'配列のための型打ちに対して特別な例外を作ったと思いました。 –

+0

@DanielFischer:それでは、実際に実装が定義されています。私の答えは – Grizzly

1

プラットフォームが内部でlongをどのように格納するかによって異なります。ユニオンの1つの要素に書き込んだり、別の要素から読み込んだりすることはできません。

1

unionデータ構造体は、その一部に書き込みを行い、他の部分から読み込むことで、未定義の動作を引き起こさない限り、移植性があります。具体的には、unsigned longへの書き込みとunsigned char[4]からの読み取り、またはその逆は、未定義の動作です。これは、ポータブルでない理由

4

一般的にエンディアンを気にする必要がある場合は、何か間違っていることがあります(シフトやマスク、シリアル化/デシリアライゼーションなど)。例えば、むしろ労働組合を持つよりも

多分あなたが何か行う必要があります。メンバーは、共用体オブジェクトの内容を読み取るために使用した場合n1570で

uint32_t pack(uint8_t byte0, uint8_t byte1, uint8_t byte2, uint8_t byte3) { 
    long result; 

    result = byte0; 
    result |= byte1 << 8; 
    result |= byte2 << 16; 
    result |= byte3 << 24; 
    return result; 
} 

uint8_t unpack(int byteNumber, uint32_t value) { 
    return (value >> (byteNumber * 8)); 
} 
+0

私がバイトに直接アクセスしようとした理由は、このようにすると、結果として得られるコードが、文字の4バイトをデータ内で4回連続してシフトさせるためです。それはint(データバイトを適切なレジスタに入れますが、依然として不要なORを行います)では良いが、longで完全に失敗する。 – KNfLrPn

関連する問題