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