2013-10-25 9 views
5

ビッグエンディアンマシンからリトルエンディアンマシンにあるデコーダに送られるデータをデコードしようとしています。私はこれを非常にうまく扱っていないし、自分自身を混乱させるような気がする。エンディアン変換C++

ビットセットを使用してデータを印刷するので、特定の32ビット構造に対してどのように出力されているかを正確に把握でき、必要なデータがビットシーケンスの途中にあることがわかります。

ここで、32ビットの値を持っていて、大きな値から小さな値へ行く場合は、バイト順序を逆にすることを知っています。私がそれをすると、私の数字は私が期待しているところで終わることはありません(手で行う)。

たとえば、私は32ビットのunsigned intを持っています。私はそれが私のビッグエンディアンマシンから0x50000000として来ていることを知っています。リトルエンディアンマシンのビットセットを使用してこれを印刷すると、cout << "packSpare 32: " << bitset<32>(Data.pack_Spare).to_string() << endl; 私は0x00005000を取得します。したがって、最初の2バイトを2番目の2バイトと順に入れ替えたように見えます。

私はもともとこのような構造体を持っていた:

それはそう、ビッグエンディアンのマシンから送信されたが、私は起こっビットのいくつかの明白なスワップに関するissureに気づいているかの逆順である
#pragma pack(push, 1) 
    struct PACK_SPARE 
    { 
     int   Spare3:28; 
     int   Heading_Reference:1; 
     int   Spare2:1; 
     int   H_Valid:1; 
     int   Spare5:1; 
    }; 
    #pragma pack(pop) 

全部を32ビットとして取り込み、スワップしてからデータを印刷したいと思っていました。今すぐ使用していますint pack_Spare;

32ビット値全体をスワップするのではなく、2つの16ビットチャンクを取り込み、それらを交換するだけですか?申し訳ありませんが、これは意味がない場合、私が言ったように、私は混乱しています。

EDIT このデータは、ネットワーク経由で来ていません。私はビデオファイルからビットをストリーミングしています。このデータを対応する値に格納します。私はビットセットを使用する場合、32ビットintの2つの16ビットのグループをバイト単位で交換するのではなく、なぜそれが変数にfreadデータを持っているのですか?私は0x50000000を期待していますが、0x00005000(0000と5000は、すべてのバイトの順序を逆にしていた典型的なエンディアンスワッピングの代わりに、スワップされています)が得られます。

+0

「hton()」または「ntoh()」の中の「network」という単語は、バイトがどこから来たのかを示すのではなく、ビッグエンディアンの「ネットワークバイトオーダー」です。 – Fozi

+0

しかし、私の問題は大きなエンディアンからリトルエンディアンに変換されていませんでした。バイトオーダーを交換することで、あるフォーマットから別のフォーマットに変換するのではなく、16ビットずつスワップしていました。 32は1-16に、1-16は17-32に)。なぜそれがそれをしていたのか分かりませんでした。 – shawleigh17

+0

あなたの問題はプロトコルレベルであると私は信じています。 – Fozi

答えて

2

私は、多くの場合、導入を越えて何のためにウィキペディアをお勧めしませんが、私が見つけたのは良いここendian discussion、(あなたの質問への答えは、なぜそれは私の32の2つの16ビットのグループ分けを交換されバイト単位で行うのではなく、バイト単位で行うのではないでしょうか?)。

このリンクのページを2/3くらいで議論しています...この探し:

enter image description here

その同じページのエンディアンに関するいくつかの興味深いものがあります。

+0

それで、本質的に、原子要素は私が期待していたものではなく、16ビットで8ビットでした。私はpowerpcからWindows 7 64ビットに向っています。 – shawleigh17

+1

その議論では、そうです、原子要素はその実装に対して_ 16ビットとして定義されています。私はPowerPCの実装に精通していませんが、あなたが見ている現象はおそらくそのようなものを示唆しています。 – ryyker

5

hton()と一緒に使用してください。ネットワークとネイティブマシンのバイトオーダー間の変換を行い、シフティングやマスキングなどの実際のビット単位の算術演算を適用します。あなたは即座のメモリアクセスで混乱する必要はありません。

4

送信時にネットワークバイトオーダー(htonX()を使用)に変換してから、読み込み時に変換する必要があります(ntohX()を使用)。

注:提供されているリンクは、Windows版の機能用です。 POSIXシステムも同様のシグネチャを持っています。

0

私が物事を並べ替えるのに使った方法は、ユニオンを使用していました。 私はEndianingsに新たなんだけど、すぐに私は、私は必要なもの、私は(私は信じて、より少ないCPUインテンシブ)を思い付く最速の方法を考え出し、folowingコードを使用していました:

template <class T, const int size = sizeof (T)> 
class cTypeConvert final 
{ 
    public: 
     union 
     { 
      T val; 
      char c [size]; 
     }uTC; 
}; 

私の場合charの文字列を使用して、私はsizeから0までcTypeConvert::uTC.c[]の配列を供給し、このテンプレートをタイプⅠとして読み込んでください。 最高の部分は、私が必要とする可能性のある標準的なタイプのものに使用できることです。

このテンプレートを使用する前に型をcharにキャストしなければならない場合は、上記の方法よりも少しだけCPUを無駄にしてしまいます。