2017-04-16 1 views
1

ネットワークパケットを介して短いintを受信して​​います。つまり、ネットワークバイトオーダー(ビッグエンディアン)で2バイトとなります。2バイトをCの短いintに結合する

受信した2バイトをマシン上のshort int変数に結合したいと思います。これはリトルエンディアンのバイトオーダーです。

例:

short int test = 400; //0x190 in big endian, 0x9001 in little endian 
char testResponse[2] = {0x01, 0x90}; 
//here is my attempt 
short int result = testResponse[1] << 8 | testResponse[0]; 
printf("%d\n", result); //-28671 when expecting 400 

任意の助けいただければ幸いです!

+0

あなたの問題は何であるのだろうか? – Olaf

+0

2つの数字を結合する方法は、ORよりも8ビットの左シフトのように見えますが、これは正しい結果を出すようには見えませんので、ビット演算が間違っていることを誰かが知っているのだろうかと思います。 –

+0

Cには「8ビットの左シフト」はありません。存在した場合、シフトカウントが「8」の場合、未定義のビヘイビアが呼び出されます。整数型のプロモーションの対象になる可能性が高いです。また、固定幅の符号なしの型を使用します。 'char'は符号なしであることが保証されておらず、8ビットであることも保証されていません。今削除された答えのあなたのコメントによると、私たちはすべての関連情報が必要です。または、私が言ったように正しいコードを取得します。 – Olaf

答えて

2
#include <arpa/inet.h> 
#include <string.h> 

int16_t result; 
memcpy(&result, testResponse, sizeof(int16_t)); 
result = (int16_t)ntohs((uint16_t)result); 

32ビットアームなどの一部のプラットフォームでは、アライメントされていないアクセスは許可されません。だからmemcpyを使ってntohを呼び出す前に正しい大きさのintに取得してください。

+0

Pedantically: '*(uint16_t *)testResponse'は' char testResponse [] 'が' uint16_t'の整列要件を満たさない可能性があるため、UBです。 – chux

+0

多くのARMプロセッサでは* pedantic *でも実用的ではありません。また、厳密なエイリアシングのコンパイラは、アラインされていないアクセスが機能するかもしれないプラットフォームであっても誤動作する可能性があります。 –

+1

@chuxが正しいです。私は整列の問題を回避するmemcpyを追加しました。 – Richard

0

あなたはインデックスを混乱させました。数字はリトルエンディアンでは0x0190ですが、ビッグエンディアンの数値は0x9001です。これは、符号付きshortでは、符号ビットへの左シフト時に整数オーバーフローが発生します。

コードは、charが署名されているか、または署名されていない可能性があります。大部分のアーキテクチャーが符号なし文字を持っているのは事実かもしれませんが、Cプログラムの大部分は符号付きcharアーキテクチャ(x86)のために書かれています。 0x90が符号拡張されているという事実は、予期しない結果を引き起こす可能性があります。

したがって、よりポータブルには

char testResponse[2] = {0x01, 0x90}; 
unsigned int tmp = (unsigned)testResponse[0] << 8 | (unsigned)testResponse[1]; 
short result = tmp; // implementation-defined behaviour 
printf("%d\n", result); // 400 
関連する問題