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

C++ 是否定义了ofstream实现的默认模式?,c++,c++11,iostream,ofstream,unspecified-behavior,C++,C++11,Iostream,Ofstream,Unspecified Behavior,给定以下代码: std::ofstream stream("somefile"); if (!stream) { return 1; } 调用.write(..)并使用stdc++和libc++时,流处于二进制模式(std::ios::binary) 然而,当使用MSVC(2015/2017RC1)时,它似乎处于文本模式或某种奇怪的状态,因为生成的文件比实际写入的文件大 但是如果我显式地设置模式std::ios::binaryMSVC的行为类似于前面提到的其他标准库的std::ofst

给定以下代码:

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;
}
使用libc++、stdc++运行时上述代码的输出:

expect: 32 
file size: 32
差异可能会更大,这取决于写入了多少数据以及数据的内容

最后,我的问题还是一样的,它是未定义的还是未指定的行为


将上面的向量更改为下面的向量可以使示例更清楚地了解发生了什么

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

流构造函数使用的默认模式是
ios\u base::out
。由于没有显式的
text
mode标志,这意味着流是以文本模式打开的。文本模式仅对Windows系统有效,它将
\n
字符转换为CR/LF对。在POSIX系统上它没有效果,文本和二进制模式在这些系统上是同义的。

流构造函数使用的默认模式是
ios\u base::out
。由于没有显式的
text
mode标志,这意味着流是以文本模式打开的。文本模式仅对Windows系统有效,它将
\n
字符转换为CR/LF对。在POSIX系统上它没有效果,文本和二进制模式在这些系统上是同义的。

当我在windows上使用
g++
libstdc++
运行代码时,我得到以下结果:

expect: 32
file size: 33
因此,问题不是特定于编译器,而是特定于操作系统


虽然C++使用单个字符<代码> \n>代码>表示字符串中的一行结束,但Windows使用两个字节<代码> > 0x0d< /COD>和<代码> 0x0a < /COD>用于文件中的行结束。这意味着,如果以文本模式将字符串写入文件,则所有出现的单个字符
\n
都将使用这两个字节写入。这就是为什么示例的文件大小会增加字节。

当我在windows上使用
g++
libstdc++
运行代码时,我得到以下结果:

expect: 32
file size: 33
因此,问题不是特定于编译器,而是特定于操作系统


虽然C++使用单个字符<代码> \n>代码>表示字符串中的一行结束,但Windows使用两个字节<代码> > 0x0d< /COD>和<代码> 0x0a < /COD>用于文件中的行结束。这意味着,如果以文本模式将字符串写入文件,则所有出现的单个字符
\n
都将使用这两个字节写入。这就是为什么示例的文件大小会增加字节。

请准确描述您看到的内容。大多少?这个文件包含什么?您的
write()
调用在哪里?演示一个。@LightnessRacesinOrbit我添加了一个示例。请准确描述您看到的内容。大多少?这个文件包含什么?您的
write()
调用在哪里?呈现一个。@LightnessRacesinOrbit我添加了一个示例。0x0A字节转换为0x0D0A,因此在向量的第三个元素中,windows下的0x0A字节是“加倍”的。那么@Torrie您是如何得出以下结论的?“调用.write(..)并使用stdc++和libc++时,流处于二进制模式(
std::ios::binary
)。”这似乎不是真的。0x0A字节被转换为0x0D0A,因此在向量的第三个元素中,windows下的0x0A字节是“加倍的”。那么@Torrie您是如何得出以下结论的?“调用….Dead……,使用STDC++ +和LBC++,流是二进制模式(<代码>:ST::iO::二进制< /代码>)。”这似乎不是真的。在Windows下的文件中,行尾由两个字节表示,值分别为
0x0D
0x0A
。巧合的是,这些值恰好与编译器在源文件中看到
'\r'
'\n
'时使用的值相同。在<代码> > \ ''//>或“代码>”\n“/CUD>和编译代码或文本文件中的任何特定值之间没有必要的连接。”字符或字符串文字中的“代码>”\n’/Cuthle结束了在每个C和C++程序中的一行。在Windows下的文件中,行尾由两个字节表示,值分别为
0x0D
0x0A
。巧合的是,这些值恰好与编译器在源文件中看到
'\r'
'\n
'时使用的值相同。
'\r'
'\n'
与编译代码或文本文件中的任何特定值之间没有必需的连接。