Team,
Could somebody please explain the below operations in the code below
struct mystruct {
char c;
long int i32;
int i16;
} s;
unsigned char *p = buf;
fread(buf, 7, 1, fp);
s.c = *p ;
s.i32 = (long)*p << 24;
s.i32 |= (long)*p << 16;
s.i32 |= (unsigned)(*p << 8);
s.i32 |= *p ;
s.i16 = *p << 8;
s.i16 |= *p ;
Basically trying to unpack the variables using the char pointer , But I did nt understand the code
for long int.
did not understand the belwo lines
s.i32 = (long)*p << 24;
s.i32 |= (long)*p << 16;
s.i32 |= (unsigned)(*p << 8);
s.i32 |= *p ;
CodePudding user response:
The code reads a 32bit signed integer in big endian format and converts it into the machine format by shifting each byte to the position it belongs.
The code also assumes CHAR_BITS == 8 but that's reasonable for most archs.
See also: https://en.cppreference.com/w/cpp/types/endian and https://en.cppreference.com/w/cpp/numeric/byteswap for how to do this better in the future.
Under POSIX you can use ntohl
from <arpa/inet.h>
.
CodePudding user response:
Let's break it down
*p // read a byte pointed to by a pointer and increment the pointer
(long)*p // cast that byte to a long
(long)*p << 24 // shift the bits of the long left (up) by 24 bits
s.i32 = (long)*p << 24; // assign the shifted bits to s.i32
So the whole process has taken one byte and placed it in bits 24 to 31 (the highest 8 bits) of a 32 bit integer.
Next step
*p // read a byte pointed to by a pointer and increment the pointer
(long)*p // cast that byte to a long
(long)*p << 16 // shift the bits of the long left (up) by 16 bits
s.i32 |= (long)*p << 16; // combine the shifted bits with the existing contents of s.i32
So this step has read another byte and placed it in bit 16 to 23 of a 32 bit integer. So we have now read bits 16 to 31 of the 32 bit integer.
I'm sure you can work out the rest for yourself. Basically it just completes bits 0 to 15 of the 32 bit integer.