2017-04-16 181 views
1

我通過網絡數據包接收短int,這意味着它將以網絡字節順序(大端)的2字節形式出現。在C中將2個字節組合成一個短int 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

結合這兩個數字的方式似乎是一個8位左移比OR,但這似乎並沒有給出正確的結果,所以我想知道是否有人知道我的位算術是錯誤的。 –

+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位arm)不允許未對齊的訪問。因此,在調用ntoh之前,請使用memcpy將其放入正確大小的int中。

+0

迂迴:'*(uint16_t *)testResponse'爲UB因爲'char testResponse []'可能不符合'uint16_t'的對齊要求。 – chux

+0

它甚至不是*迂腐的*但在許多ARM處理器上實用。而且,嚴格別名,編譯器甚至可能在未對齊訪問可能工作的平臺上行爲不端。 –

+1

@chux是正確的。我已經添加了一個memcpy來解決對齊問題。 – Richard

0

你已經混淆了指數。小端的數字爲0x0190,但是您的代碼會計算大端數字,即0x9001,它在有符號的short中也會在左移到符號位時導致整數溢出。

該代碼確實不是很便攜,因爲char可能有符號或無符號。雖然大多數體系結構都有無符號字符也許是事實,但事實是,大多數C程序都是爲簽名字符體系結構(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