2016-10-30 2 views
1

私はTCPソケットのメッセージを受け取り、uint8_tの配列に格納しようとしています。 受信するバッファは8バイト長で、4つの一意の値を含んでいます。 バイト1:uint8_tの値1、バイト2-3:uint16_tの値2、バイト4:uint8_tの値3、バイト5-8:符号なしlongの値4。 エンディアンはビッグエンディアンのオーダーです。uint8_tの配列からさまざまなサイズの値を抽出する方法は?

int numBytes = 0; 
uint8_t buff [8]; 
if ((numBytes = recv(sockfd, buff, 8, 0)) == -1) 
{ 
    perror("recv"); 
    exit(1); 
} 

uint8_t *pt = buff; 
printf("buff[0] = %u\n", *pt); 
++pt; 
printf("buff[1] = %u\n", *(uint16_t*)pt); 

ただし、2番目のprintfは予期しない値を出力します。私は2バイトを抽出するために何かを間違ってやったのですか、あるいは私の印刷機能に何か問題がありますか?

+0

お答えすることは不可能で、あなたが何を「バイト2-3:値2」を説明するまでの手段、それらのバイトが値に変換されなければならない、すなわち、どのように。値4と同じです。 –

+0

マルチバイト値のエンディアンはわかりませんが、配列として 'buff'を直接索引付けするのではなく、ポインタを使用して問題を複雑にする目的がありません。要素ごとに値を設定します。 –

+0

私には明らかな@PeteBecker:値2は第2の値を意味します。 –

答えて

1

おそらく、この(ビッグエンディアン)

uint8_t buff [8]; 
// ... 
uint8_t  val1 = buff[0]; 
unit16_t  val2 = buff[1] * 256 + buff[2]; 
unit8_t  val3 = buff[3]; 
unsigned long val4 = buff[4] * 16777216 + buff[5] * 65536 + buff[6] * 256 + buff[7]; 
2

のようなあなたのデータがバッファに到着した後の世話をするために2つの問題を持っています。

最初はcharを別名設定できるので、唯一char*に非char型ポインタをキャストすることによって達成されるエイリアシング規則に従っています。 neverchar*を非char型ポインターにキャストする必要があります。

第2は、ネットワーク上で送信された整数が転送前にネットワーク順序に変換され、受信後にネットワーク順序から変換されるネットワークバイト順序プロトコルに従っています。このために我々は一般にhtons,htonl,ntohsおよびntohlを使用する。

このような何か:

// declare receive buffer to be char, not uint8_t 
char buff[8]; 

// receive chars in buff here ... 

// now transfer and convert data 
uint8_t a; 
uint16_t b; 
uint8_t c; 
uint32_t d; 

a = static_cast<uint8_t>(buff[0]); 

// always cast the receiving type* to char* 
// never cast char* to receiving type* 
std::copy(buff + 1, buff + 3, (char*)&b) 

// convert from network byte order to host order 
b = ntohs(b); // short version (uint16_t) 

c = static_cast<uint8_t>(buff[3]); 

std::copy(buff + 4, buff + 8, (char*)&d) 

d = ntohl(d); // long version (uint32_t) 
+0

これは受け入れられた答えよりも良い答えです。 – YSC

関連する問題