我认为这是一个字节序问题。即您将字节 42 和 4D 放入您的 short 值中。但是您的系统是小端(我可能有错误的名称),它实际上从左到右而不是从右到左读取字节(在多字节整数类型内)。
在此代码中演示:
#include <stdio.h>
int main()
{
union {
short sval;
unsigned char bval[2];
} udata;
udata.sval = 1;
printf( "DEC[%5hu] HEX[%04hx] BYTES[%02hhx][%02hhx]\n"
, udata.sval, udata.sval, udata.bval[0], udata.bval[1] );
udata.sval = 0x424d;
printf( "DEC[%5hu] HEX[%04hx] BYTES[%02hhx][%02hhx]\n"
, udata.sval, udata.sval, udata.bval[0], udata.bval[1] );
udata.sval = 0x4d42;
printf( "DEC[%5hu] HEX[%04hx] BYTES[%02hhx][%02hhx]\n"
, udata.sval, udata.sval, udata.bval[0], udata.bval[1] );
return 0;
}
给出以下输出
DEC[ 1] HEX[0001] BYTES[01][00]
DEC[16973] HEX[424d] BYTES[4d][42]
DEC[19778] HEX[4d42] BYTES[42][4d]
因此,如果您想要便携,则需要检测系统的字节序,然后在需要时进行字节洗牌。互联网上有很多交换字节的例子。
后续问题:
我问只是因为我的文件大小是 3 而不是 196662
这是由于内存对齐问题。 196662 是字节 36 00 03 00,3 是字节 03 00 00 00。大多数系统需要像int 这样的类型,而不是在多个内存words 上拆分。如此直观地,您认为您的结构在内存中布局如下:
Offset
short magic_number; 00 - 01
int file_size; 02 - 05
short reserved_bytes[2]; 06 - 09
int data_offset; 0A - 0D
但是在 32 位系统上,这意味着 files_size 在与 magic_number 相同的 word 中有 2 个字节,在下一个 word 中有两个字节。大多数编译器不会支持这一点,所以结构在内存中的布局方式实际上是这样的:
short magic_number; 00 - 01
<<unused padding>> 02 - 03
int file_size; 04 - 07
short reserved_bytes[2]; 08 - 0B
int data_offset; 0C - 0F
因此,当您读取 36 00 中的字节流时,您的填充区域将让您的 file_size 得到 03 00 00 00。现在,如果您使用fwrite 创建此数据,它应该没问题,因为填充字节会被写出。但是,如果您的输入总是采用您指定的格式,那么将整个结构与 fread 一起读取是不合适的。相反,您需要单独阅读每个元素。