我想知道 IO 流是否真的是可移植的(我认为它们应该是但要确定)?特别是在处理 unix 和 windows 中使用的文件时。
具体来说,如果我将一个双精度值转储到 Windows 中的文件中,然后使用 iostreams 从文件中读取 unix 上的相同值,是否不会因为两个操作系统的字节序变化而导致问题?
格式化的 io 呢?我在某个地方读到,不确定在哪里,当涉及到处理格式化数据时,windows 和 unix 处理相同的方式存在一些差异。任何人都可以对这个问题有所了解吗?
我想知道 IO 流是否真的是可移植的(我认为它们应该是但要确定)?特别是在处理 unix 和 windows 中使用的文件时。
具体来说,如果我将一个双精度值转储到 Windows 中的文件中,然后使用 iostreams 从文件中读取 unix 上的相同值,是否不会因为两个操作系统的字节序变化而导致问题?
格式化的 io 呢?我在某个地方读到,不确定在哪里,当涉及到处理格式化数据时,windows 和 unix 处理相同的方式存在一些差异。任何人都可以对这个问题有所了解吗?
C++ 标准是抽象的,没有提到任何特定的操作系统(AFAIK)。因此,iostream 库是可移植的。话虽如此,C++ 标准允许某些实现细节,包括一些对用户可见的(而不仅仅是隐藏在标准 C++ 库中)依赖于实现的细节。这允许操作系统和/或编译器的提供者选择他们首选的方式来实现 C++ 标准。
任何依赖于实现相关行为的代码显然是不可移植的,即使在同一操作系统和/或编译器的不同版本中也是如此。换句话说,应该避免这样的代码。
注意:有时需要编写依赖于实现的代码。在这种情况下,必须保护代码不破坏假定的依赖于实现的行为。例如,一个程序可能假设sizeof(long unsigned)==8
. 在这种情况下,至少static_assert(sizeof(long unsigned)==8,"long unsigned not 8 bytes")
应该停止编译无效代码,但理想情况下应该存在替代版本,并通过模板魔术(或 C 风格的宏)来选择。C++11 标准实际上为类型提供了std::uint64_t
保证( sizeof(std::uint64_t)==8
和类似的)以避免此类问题。但是,sizeof(ostream)
仍然依赖于实现。
文件输入输出:是的,它们是兼容的。Unix 中的比特流与 Windows 中的比特流相同。Unix 中的 double 值与 Windows 相同,都遵循标准。
格式:我不知道任何二进制格式(在双精度示例中),您可能正在谈论文本。Windows 中的文本格式与 Unix 不同,这是导致许多问题的原因。
二进制接口/代码可移植性:如果您使用 IO 函数,那么它是不可移植的。std::input/output 流,即 f/o/stream 实现不是可移植的,也不是为可移植而设计的。
它是可移植的,如果您从一个系统写入特定的字节序列,将该序列传输到另一个系统(通过文件或套接字,这并不重要),您可以在另一边。如果您以文本模式而不是二进制模式编写或阅读,那么行尾(我认为理论上其他实现定义的特殊字符)可能会被重新解释。
不可移植的是作为字节序列的精确表示,double
无论是二进制的还是格式化的。二进制是因为例如字节序,而格式化是因为运行时库中的细微差异,这可能意味着当一个系统编码为字符串并由另一个系统编码为字符串时,您的结果可能与 ulp(或有时更多)不同double
,即使您输出应该足够精确的十进制数字。NaN 值的字符串表示也留给实现。
就 C++ 标准而言,double
不需要是 IEEE 双精度值。因此,理论上二进制表示之间可能没有任何共同点,并且在可以表示哪些值以及因此在执行格式化 I/O 时输出/接受哪些字符串方面也存在很大差异。在实践中,IEEE 是常用的,字符串通常不会引入比您在浮点运算中预期的更多的错误。