2017-04-16 107 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