是已定义的流的实现的默认模式



给定以下代码:

std::ofstream stream("somefile");
if (!stream)
{
   return 1;
}

调用 .write(....)以及使用 stdc libc 该流处于二进制模式(std::ios::binary)。

但是,当使用 MSVC (2015/2017RC1)时,它似乎处于文本模式或某些怪异之处,因为结果文件大于实际写的文件。

但是,如果我明确设置模式std::ios::binary MSVC的行为与前面提到的其他标准库的std::ofstream实现相似。


示例代码:

#include <vector>
#include <cstdio>
#include <fstream>
std::size_t fsz(const char* filename) {
    std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
    return static_cast<std::size_t>(in.tellg());
}
int main() {
   std::ofstream stream("filename");
   if (!stream)
      return 1;
   std::vector<unsigned long long int> v = {0x6F1DA2C6AC0E0EA6, 0x42928C47B18C31A2, 0x95E20A7699DC156A, 0x19F9C94F27FFDBD0};
   stream.write(reinterpret_cast<const char*>(v.data()),v.size() * sizeof(unsigned long long int));
   stream.close();
   printf("expect: %dn", v.size() * sizeof(unsigned long long int));
   printf("file size: %dn", fsz("filename"));
   return 0;
}

使用MSVC运行时的上述代码输出:

expect: 32 
file size: 33

使用libc 运行时,输出上述代码,stdc :

expect: 32 
file size: 32

差异可能会变得更大,这取决于编写了多少数据以及数据的内容。

最后,我的问题仍然相同,是未定义还是未指定的行为?


将上述向量更改为以下内容,使该示例更加明显。

std::vector<unsigned long long int> v = {0x0A0A0A0A0A0A0A0A, 0x0A0A0A0A0A0A0A0A, 0x0A0A0A0A0A0A0A0A, 0x0A0A0A0A0A0A0A0A};

流构造器使用的默认模式为 ios_base::out。由于没有明确的text模式标志,因此这意味着流在文本模式下打开。文本模式仅对Windows系统具有影响,在该系统将n字符转换为CR/LF对。在POSIX系统上,它没有效果,文本和二进制模式在这些系统上是同义词。

使用g++libstdc++在Windows上运行您的代码时,我会得到以下结果:

expect: 32
file size: 33

因此,问题不是具体编译器,而是特定于OS的问题。

虽然C 使用单个字符n表示字符串中结尾的行,但Windows使用两个字节0x0D0x0A用于在文件中结束的行。这意味着,如果您在文本模式下将字符串写入文件,则使用这两个字节编写单个字符n的所有出现。这就是为什么您在示例的文件大小中获得其他字节的原因。

相关内容

  • 没有找到相关文章

最新更新