std::ofstream 在从 256 开始的字节边界上写入整数时出现奇怪的行为

std::ofstream weird behavior when writing integers on byte border from 256

试图创建二进制文件格式,但行为很奇怪。

    std::ofstream outputFile;
    outputFile.open (PATH, std::ios_base::out | std::ios_base::binary |
    std::ios_base::app);
    unsigned long long int timer3 = 255;
    outputFile <<reinterpret_cast<const char *>(&timer3);
    timer3 = 256;
    outputFile <<reinterpret_cast<const char *>(&timer3);
    timer3 = 257;
    outputFile <<reinterpret_cast<const char *>(&timer3);
    timer3 = 258;
    outputFile <<reinterpret_cast<const char *>(&timer3);

二进制输出文件仅包含(十六进制) FF 01 01 02 01

FF- 255

01 01- 257

02 01 -258

为什么它公然无视 256(和 512、1024..)?

将整数逐个整数写入二进制的最佳方法是什么?

使用流运算符 (<<) 将 char* 写入文件时,它会在第一次终止 NULL (= 0) 时停止。

255 在 Little-Endian 中将被翻译成 0xff 0 0 0 因此它只写 0xff

256 将被翻译成 0 0x01 0,因此它被认为是一个空字符串,因为它从 0 开始。

257 将被翻译成 0x01 0x01 0,所以它会被打印出来。

任何第一个字节为 0 的数字(例如 512、768、1024 都是 256 的倍数)都不会用您的方法打印(在 Little Endian 机器上,例如 Windows 和 Linux) 因为第一个字节是 0.

通过使用格式化的插入运算符 << 并给它一个 const char*,你告诉流你给它一个 C 字符串,即一个空终止序列要解释为字符的字节。

但事实并非如此。

事实上,任何具有 "null" 组件(任何字节设置为零)的 long long 值都将终止该格式化插入。

<< 怎么知道什么时候停止?

您应该改用 outputFile.write(...),因为这是 "raw" 字节直接插入流的方式。

outputFile.write(reinterpret_cast<const char *>(&timer3), sizeof(timer3));

请注意,除非您在文件中写入一些指示符来告诉读者这些值是以 endianness 写入的,否则您将永远无法再次明确地读出它们。 (但是,对于一个简单的、不可移植的应用程序,这可能不是一个考虑因素。)