要么您的 C++ 标准库副本损坏,要么您正在做一些您没有告诉我们的事情。简而言之,默认的预期行为是以十进制格式输出整数值,而不管符号类型如何。仅考虑类型符号以确保当输出格式设置为十进制时未将无符号值格式化为有符号值。
也就是说,让我们去标准地旅行吧……
您感兴趣的关键信息是格式化如何应用于无符号整数。我将尝试突出标准中适用于输出格式(关于您的问题)以及如何处理整数的重要部分。首先查看operator<<
处理整数类型时的工作原理。这在 $27.7.3.6.2 中定义。
从 $27.7.3.6.2/1 - 算术插入器[ostream.inserters.arithmetic]
运算符<<(布尔值);
运算符<<(短值);
运算符<<(无符号短值);
运算符<<(int val);
运算符<<(无符号整数值);
运算符<<(long val);
运算符<<(无符号长值);
运算符<<(long long val);
运算符<<(unsigned long long val);
运算符<<(浮点值);
运算符<<(双值);
运算符<<(long double val);
运算符<<(const void* val);
1 效果:类 num_get<> 和 num_put<> 处理依赖于语言环境的数字格式和解析。
num_put
实际上负责处理整数值的格式。
从 $22.4.2.2.2/5 num_put 虚拟函数 [facet.num.put.virtuals]
阶段 1:阶段 1 的第一个动作是确定转换说明符。描述此确定的表使用以下局部变量
fmtflags 标志 = str.flags() ;
fmtflags basefield = (flags & (ios_base::basefield));
fmtflags 大写 = (flags & (ios_base::uppercase));
fmtflags floatfield = (flags & (ios_base::floatfield));
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
.
从 $27.5.3/2 类 ios_base [ios.base]
- 它维护几种数据:
— 影响如何解释(格式化)输入序列和如何生成(格式化)输出序列的控制信息;
需要考虑的另一个重要方面是初始化流时的默认标志值。这些在不同的表中列出。具体来说,表 128 描述了调用basic_ios::init()
对流的影响。供参考std::basic_ios
继承自std::ios_base
. std::basic_ios
是一个基类,std::basic_ostream
用于提供专门的流std::ostream
等。
从 $27.5.5.3 表 128 - basic_ios::init() 效果
Elements Flags
-----------------------------
flags() skipws | dec
这意味着 afterinit()
被调用的调用flags()
应该总是返回一个与 相同的值(skipws | dec)
。
把这一切放在一起,这意味着需要一个新初始化的流来格式化十进制整数值,而不管类型 sign。
[C++03 和 C++11 的关键部分似乎相同]