是否定义了 ofstream 实现的默认模式?

Is the default mode of ofstream implementation defined?

给定以下代码:

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: %d\n", v.size() * sizeof(unsigned long long int));
   printf("file size: %d\n", 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 都将使用这两个字节写入。这就是为什么您的示例文件大小会增加额外字节的原因。