给定以下代码:
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使用两个字节0x0D
和0x0A
用于在文件中结束的行。这意味着,如果您在文本模式下将字符串写入文件,则使用这两个字节编写单个字符n
的所有出现。这就是为什么您在示例的文件大小中获得其他字节的原因。