谁能帮我理解这段代码中操作的目的:
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++;
基本上,它似乎试图使用char指针解包变量。但是我不理解与long int
相关的代码,特别是以下代码:
s.i32 = (long)*p++ << 24;
s.i32 |= (long)*p++ << 16;
s.i32 |= (unsigned)(*p++ << 8);
s.i32 |= *p++;
该代码读取一个32位带符号的大端整数,并通过将每个字节移动到它所属的位置将其转换为机器格式。
代码也假设CHAR_BITS == 8,但这对大多数arch来说是合理的。
参见:https://en.cppreference.com/w/cpp/types/endian和https://en.cppreference.com/w/cpp/numeric/byteswap了解如何在将来做得更好。
在POSIX下,可以从<arpa/inet.h>
使用ntohl
。
让我们来分析一下
*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
所以整个过程取了一个字节,并把它放在32位整数的24到31位(最高的8位)上。
下一步
*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
因此,这一步读取了另一个字节,并将其放置在32位整数的16位到23位。因此,我们现在已经读取了32位整数的第16到31位。
我相信你可以自己解决剩下的问题。基本上,它只完成32位整数的0到15位。