如果您有二进制输出流,并将整数写入32位Windows计算机上的文件。那么,你能在64位Windows计算机上从同一个文件中读取相同的整数吗?
我的猜测是否。由于32位计算机上的整数是4个字节,而64位计算机中的整数是8个字节。
以下代码也是如此,而文件必须能够从64位和32位计算机读取和写入,无论操作系统、计算机体系结构和数据类型如何。如果不是,当文件必须是二进制形式时,如何才能做到这一点。
写作
std::ofstream ofs("example.bin", std::ios::binary);
int i = 128;
ofs.write((char*) (&i), sizeof(i));
ofs.close();
阅读
std::ifstream ifs("example.bin", std::ios::binary);
int i = 0;
ifs.read((char*) (&i), sizeof(i));
ifs.close();
虽然int
在几乎所有现代平台(32位和64位)上都是4字节,但其大小无法保证。因此,为了将数据序列化到文件或其他二进制流中,您应该更喜欢在C++11中引入的头<cstdint>
中的固定宽度整数类型(一些编译器在C++03中支持它):
#include <cstdint>
...
int32_t i = 128;
ofs.write((char*)(&i), sizeof(i));
...
另一种选择是强制特定类型具有特定大小,例如int
具有大小4。如果这不是真的,为了确保你的程序不会编译,请使用static_assert
:
...
int i = 128;
static_assert(sizeof(i) == 4, "Field i has to have size 4.");
ofs.write((char*)(&i), sizeof(i));
...
考虑到我们有如上所述的固定宽度整数,这听起来很愚蠢,但如果你想将你所做假设的整个结构存储在某个库的某个版本中,这可能会很有用。示例:glm
中的vec4
被记录为包含四个浮点,因此在序列化此结构时,最好静态检查它,以便捕捉未来的库更改(不太可能,但可能)。
然而,需要考虑的另一件非常重要的事情是整型的endianes,它在不同的平台之间有所不同现代x86桌面平台的大多数编译器都使用little-endian作为整型,所以我更喜欢这种二进制文件格式;但是,如果平台使用big-endian,则需要对其进行转换(颠倒字节顺序)。
在C++中无法保证int的大小。你所知道的是,它至少和短int一样大,不比长int大。编译器可以在这些约束条件下自由选择合适的大小。虽然大多数人会选择32位作为int的大小,但有些人不会。
如果您知道您的类型总是32位,那么您可以使用int32_t类型。
include <stdint.h>
以获得此类型。