我认为当使用">>" "<<"流操作符时,无符号整数类型被序列化/反序列化为二进制数据,而有符号整数类型被序列化为格式化文本。
我的假设是:
uint32_t a= 17;
int b= 54321;
file_out<<a; //write 0x00000011 to the file according to some endiannes
file_out<<b; //write following ASCII characters '5''4''3''2''1' to the file.
我的假设是否在某种标准中被明确陈述?如果是,下面哪个更快?
file_out<<a;
或
file_out.write((char*)&a,sizeof(uint32_t);
编译器和库MinGW.
特别奇怪的是,相同的流类型根据输入类型提供不同的行为。
或者你的c++标准库副本坏了或者你正在做一些你没有告诉我们的事情。简而言之,默认的预期行为是以十进制格式输出整数值,而不管类型符号是什么。考虑类型符号只是为了确保当输出格式设置为十进制时,不将无符号值格式化为有符号值。
那就是说,让我们去标准之地旅行…
您感兴趣的关键信息是如何将格式化应用于无符号整数。我将尝试强调标准中适用于输出格式的重要部分(关于您的问题)以及如何处理整数。首先看看operator<<
在处理整数类型时是如何工作的。在$27.7.3.6.2中定义。
From $27.7.3.6.2/1 -算术插入器[ostream.inserters.arithmetic]
operator<& lt; (bool val);
operator<& lt; (val);
Operator<<(unsigned short val);
operator<& lt; (int val);
操作符<<(unsigned int);
长operator<& lt; (val);
Operator<<(unsigned long val);
操作符<<(long long val);
操作符<<(unsigned long long val);
operator<& lt;(浮动val);
operator<& lt;(双val);
Operator<<(long double val);
(const void* val);1效果:类num_get<>和num_put<>处理依赖于语言环境的数字格式化和解析。
num_put
实际上负责处理整数值的格式化。
From $22.4.2.2/5 num_put virtual functions [facet.num.put.virtuals]
阶段1:阶段1的第一个动作是确定转换说明符。描述这种判断的表使用以下局部变量
fmtflags = str.flags();
Fmtflags basefield = (flags &(ios_base:: basefield));
Fmtflags大写= (flags &(ios_base::大写));
Fmtflags floatfield = (flags &(ios_base::实域));
Fmtflags showpos = (flags &(ios_base:: showpos));
Fmtflags showbase = (flags &(ios_base:: showbase));用于描述阶段1的所有表都是有序的。也就是说,应用条件为真的第一行。当前面的行都不适用时,不带条件的行是默认行为。对于从非字符类型的整型转换,函数确定了表87所示的整型转换说明符。
Table 87 — Integer conversions State stdio equivalent basefield == ios_base::oct %o (basefield == ios_base::hex) && !uppercase %x (basefield == ios_base::hex) %X for a signed integral type %d for an unsigned integral type %u
上面有两个关键的信息,除了。basefield
表示数值格式,且判定为有序。basefield
很重要,因为它决定了输出的值是十六进制、十进制还是八进制等。流需要根据格式标志对整型值进行格式化。注意,为了将值格式化为十六进制,必须设置ios_base::hex
标志。
格式标志源自ios_base
。
From $27.5.3/2 Class ios_base [ios.base]
另一个需要考虑的重要方面是初始化流时的默认标志值是什么。这些列在另一个表中。特别是表128,它描述了调用
- 它维护几种数据:
-影响如何解释(格式化)输入序列和如何生成(格式化)输出序列的控制信息;
basic_ios::init()
对流的影响。作为参考,std::basic_ios
继承自std::ios_base
。std::basic_ios
是std::basic_ostream
的基类,用于提供专用流std::ostream
等。
表128 - basic_ios::init() effects
Elements Flags
-----------------------------
flags() skipws | dec
这意味着在init()
被调用之后,对flags()
的调用应该总是返回与(skipws | dec)
相同的值。
把这些放在一起,这意味着无论类型符号如何,新初始化的流都需要以十进制格式格式化整型值。