Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting big endian structures to little endian

I'm making a C program that communicates with a patient monitor that uses big endian byte ordering. For example, if I've certain C structure

typedef struct {
   int short a;
   int short b;
   int       c;
} msg;

To read this kind of structure, I can simply use ntohs(msg.a), ntohs(msg.b), ntohl(msg.c). But some of the structure has a buffer of short integers but that buffer itself is type of an another structure. For example,

typedef struct {
   int short length;
   int short b[MAX_BUF_SIZE];
} msg1;

The field "b" in above structure represents an another structure, which is below:

typedef struct {
   int short a;
   int short b;
} msg2;

Now, my question is 1) should I convert all the short integers of structure "msg1" to host order and then cast it to pointer of type "msg2" and simply read "msg2.a" and "msg2.b" or 2) I should convert the byte ordering of "msg2.a" and "msg2.b" as well or 3) just cast "msg1.b" to pointer of type "msg2" and read "msg2.a" and "msg2.b" by converting each of them to host order?

Please tell which one of the approach is correct to read msg1

APPROACH 1

int t[msg1.length];
for(int i = 0; i < msg1.length; i++)
   t[i] = ntohs(*(msg1.b + i));
msg2 * msg2_m = (msg2 *)t;
/* should I convert the msg2_m.a and msg2_m.b as well? */
printf("%d:%d", msg2_m.a, msg2_m.b);

APPROACH 2

All same except

printf("%d:%d", ntohs(msg2_m.a), ntohs(msg2_m.b));

APPROACH 3

Not converting "msg1.b" and directly casting "msg1.b" to "msg2" and just convert "msg2.a" and "msg2.b" to host order.

msg2 *msg2_m = (msg2 *)msg1.a;
printf("%d:%d", ntohs(msg2_m.a), ntohs(msg2_m.b));

I need to understand when a structure is casted to some other structures does its byte ordering are changed according to the new structure when passed across network? I think APPROACH 3 is correct, but thats just me, I'm not sure about internals of byte ordering. Any help would be appreciated.

Thanks, Shivam Kalra

like image 590
Shivam Avatar asked Jan 20 '12 00:01

Shivam


People also ask

How do you convert big-endian to little endian?

This C# program is used to convert big endian to little endian. We have defined the value of 'little' variable as 2777. The BitConverter is used to convert the given integer value to bytes and reverse the value using Reverse() function.

What is Swap endianness?

The SWAP_ENDIAN function reverses the byte ordering of arbitrary scalars, arrays or structures. It can make “big endian” number “little endian” and vice-versa. Note: The BYTEORDER procedure can be used to reverse the byte ordering of scalars and arrays (SWAP_ENDIAN also allows structures).

How do you convert to little endian in Python?

To make this work with negative integers you need to mask your input with your preferred int type output length. For example, -16 as a little endian uint32_t would be bytearray. fromhex(hex(-16 & (2**32-1))[2:])[::-1] , which evaluates to bytearray(b'\xf0\xff\xff\xff') .

Is x64 big or little endian?

The IA-32 and x86-64 instruction set architectures use the little-endian format.


1 Answers

First, casting does not affect byte order.

Second, you don't want to be thinking about byte order everywhere in your code because you or someone else will forget and make a mistake somewhere and it will be hell trying to find the bug later. So, as soon as you read the data in, convert it to the correct byte order. If you read a struct in that contains an array of shorts, convert the whole array of shorts to the correct byte order immediately. The same goes for any other structs. Convert the data and store the result; don't just use ntohs each time you need to read or print something. Segregate this code from the rest of your program so that you can forget about byte order in the other parts of the program and only think about byte order when you're dealing with the conversion code.

like image 113
Kyle Jones Avatar answered Sep 30 '22 10:09

Kyle Jones