Jeremy Robertson
Jeremy Robertson

Reputation: 115

Combine 2 bytes into a short int in C

I am receiving a short int via network packet, which means it would come as 2 bytes in network byte order (big endian).

I would like to combine the two bytes I received into a short int variable on my machine, which is little endian byte order.

Example:

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

Any help would be appreciated!

Upvotes: 2

Views: 5040

Answers (2)

Richard
Richard

Reputation: 241

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

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

Some platforms, such as 32-bit arm, don't allow unaligned accesses. So use memcpy to get it into a correctly sized int before calling ntoh.

Upvotes: 3

You've confused the indices. The number is 0x0190 in little endian, but your code calculates the big-endian number, which is 0x9001, which, in signed short will also cause integer overflow upon left-shift to the sign bit.

The code indeed isn't very portable as char might be signed or unsigned. While it might be true that majority of architectures have unsigned chars, the truth is that majority of C programs are written for signed char architecture - the x86. There the fact that 0x90 is sign-extended might cause wild unexpected results.

Thus more portable would be

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

Upvotes: 0

Related Questions