为何Win32 ReadFile()写入uint16_t数组时字节顺序不保留?
问题
我有一个二进制文件,包含如下十六进制数据:
00e0 a248 6000 611e 6200 d202 d212 7208 3240 120a 6000 613e 6202 a24a d02e d12e ...
当使用ReadFile()并将目标缓冲区设为uint8_t数组时,写入的缓冲区数据与源文件一致:
uint8_t rom[256]; ReadFile(_, rom, _, NULL, NULL); // in rom rom[0x00000000] 0x00 rom[0x00000001] 0xe0 rom[0x00000002] 0xa2 rom[0x00000003] 0x48 rom[0x00000004] 0x60 rom[0x00000005] 0x00 rom[0x00000006] 0x61 ...
为何当使用ReadFile()搭配uint16_t数组时,每个元素的字节顺序会反转?
uint16_t rom[256]; ReadFile(_, rom, _, NULL, NULL); // in rom rom[0x00000000] 0xe000 rom[0x00000001] 0x48a2 rom[0x00000002] 0x0060 rom[0x00000003] 0x1e61 rom[0x00000004] 0x0062 rom[0x00000005] 0x02d2 rom[0x00000006] 0x12d2 ...
更大的数据类型也存在同样的情况:
uint32_t rom[256]; ReadFile(_, rom, _, NULL, NULL); // in rom rom[0x00000000] 0x48a2e000 rom[0x00000001] 0x1e610060 rom[0x00000002] 0x02d20062 rom[0x00000003] 0x087212d2 rom[0x00000004] 0x0a124032 rom[0x00000005] 0x3e610060 rom[0x00000006] 0x4aa20262 ...
而ReadFile()的文档中并未提及该行为。
解答
这不是ReadFile()的问题,而是**CPU字节序(endianness)**导致的:
ReadFile()只是按原始字节流读取文件内容,它不会修改任何字节的顺序,只是把文件里的字节依次写入内存缓冲区。- 你使用的是x86/x86_64架构的CPU,这类CPU采用**小端序(Little Endian)**存储多字节数据:多字节数值的最低有效字节(LSB)存在内存低地址,最高有效字节(MSB)存在内存高地址。
- 举个具体例子:文件里前两个字节是
0x00(低地址)和0xE0(高地址),用uint16_t存储时,CPU会把0x00当作最低有效字节,0xE0当作最高有效字节,组合后就是0xE000;同理文件里的0xA2和0x48会被解析为0x48A2。 uint8_t是单字节类型,不存在字节顺序问题,所以和文件内容完全一致。
如果需要让多字节类型的解析结果和文件的字节顺序一致(大端序),可以手动转换字节序,比如使用_byteswap_ushort()(针对uint16_t)、_byteswap_ulong()(针对uint32_t)这类函数,或者自己实现字节反转逻辑。
内容的提问来源于stack exchange,提问作者yun
相关产品推荐
相关产品推荐

