说清楚 std::cout<<std::hex<<std::endl 到底是什么意思
------------------------------------------------------------
author:hjjdebug
date: 2023年 07月 12日 星期三 17:29:32 CST
------------------------------------------------------------
cout<<hex;
cout<<endl;
一直不太清楚这样的写法到底是什么含义?执行了什么操作.
咱也认真查查头文件,看看到底是什么.
------------------------------------------------------------
1.
# 在 "/usr/include/c++/9/iostream" 第60行, 定义了cout 为ostream
ostream cout;
------------------------------------------------------------
2.
#在 "/usr/include/c++/9/bits/ios_base.h" 872行, 定义了hex 为一个函数,其参数是ios_base
--------------------------------------------------------------------------------
inline ios_base&
hex(ios_base& __base)
{
__base.setf(ios_base::hex, ios_base::basefield);
return __base;
}
进一步查ios_base::basefield 为一个静态全局变量,用做mask,其初始值是3值相或.
/// A mask of dec|oct|hex. Useful for the 2-arg form of @c setf.
static const fmtflags basefield = _S_basefield;
_S_basefield = _S_dec | _S_oct | _S_hex,
进一步查ios_base::hex 为一个数值
static const fmtflags hex = _S_hex;
这个符号的数值按如下定义:
enum _Ios_Fmtflags
{
_S_boolalpha = 1L << 0,
_S_dec = 1L << 1,
_S_fixed = 1L << 2,
_S_hex = 1L << 3,
_S_internal = 1L << 4,
_S_left = 1L << 5,
_S_oct = 1L << 6,
_S_right = 1L << 7,
_S_scientific = 1L << 8,
_S_showbase = 1L << 9,
_S_showpoint = 1L << 10,
_S_showpos = 1L << 11,
_S_skipws = 1L << 12,
_S_unitbuf = 1L << 13,
_S_uppercase = 1L << 14,
_S_adjustfield = _S_left | _S_right | _S_internal,
_S_basefield = _S_dec | _S_oct | _S_hex,
_S_floatfield = _S_scientific | _S_fixed,
_S_ios_fmtflags_end = 1L << 16,
_S_ios_fmtflags_max = __INT_MAX__,
_S_ios_fmtflags_min = ~__INT_MAX__
};
typedef _Ios_Fmtflags fmtflags;
进一步查setf 的实现把对象的 _M_flags 进行了更改.
fmtflags setf(fmtflags __fmtfl, fmtflags __mask)
{
fmtflags __old = _M_flags;
_M_flags &= ~__mask;
_M_flags |= (__fmtfl & __mask);
return __old;
}
--------------------------------------------------------------------------------
3.
# 在 "/usr/include/c++/9/iostream" 第107行, 定义了 ostream操作符<< 对指针函数的抽取操作
__ostream_type& operator<<(__ios_type& (*__pf)(__ios_type&))
{
__pf(*this);
return *this;
}
对于std::<< 操作符,已经定义了其左手侧就是iostream 对象(this 对象), 右手侧就是第一参数
如果右手侧参数是一个特殊的函数,就执行这个函数并返回 *this.
--------------------------------------------------------------------------------
现在我们可以对 cout<<hex 做总结了.
<<重载,其左手侧是this对象cout,右手侧是hex函数,结果是执行hex函数,
hex函数执行结果是把cout的_M_flags 置位成_S_hex,并返回*this 对象
std::endl ,也是一个函数.
extern template ostream& endl(ostream&);
看看这个函数的实现. 或者说这个函数干了什么?
它输出了一个'\n' 并且还flush这个cout (当用cout做this 对象时)
# "/usr/include/c++/9/ostream" 第609行
endl(basic_ostream<_CharT, _Traits>& __os)
{ return flush(__os.put(__os.widen('\n'))); }
可见它输出了"\n"并flush了对象
还有一些细节,何以ostream 一会是ios_base,一会又是ios_type,一会又是basic_ostream<>就没有太追了.
架构理解了就不会晕菜了.