从 C++0x FDIS (N3290) 的第 18.4.1 [cstdint.syn] 中,int8_t
是一个可选的 typedef,指定如下:
namespace std {
typedef signed integer type int8_t; // optional
//...
} // namespace std
§ 3.9.1 [basic.fundamental] 规定:
有五个标准有符号整数类型: “signed char
”, “short int
”, “int
”, “long int
”, and “long long int
”。在此列表中,每种类型至少提供与其前面的列表一样多的存储空间。也可能有实现定义的扩展有符号整数类型。标准和扩展有符号整数类型统称为有符号整数类型.
...
Types bool
, char
, char16_t
, char32_t
, wchar_t
,有符号和无符号整数类型统称为整数类型。整型的同义词是整数类型.
§ 3.9.1 还规定:
在任何特定的实现中,一个简单的char
对象可以采用与 a 相同的值signed char
or an unsigned char
;哪一个是实现定义的。
人们很容易得出这样的结论:int8_t
可能是一个 typedefchar
假如char
对象具有带符号的值;然而,情况并非如此char
不在列表之中有符号整数类型(标准和可能扩展的有符号整数类型)。也可以看看Stephan T. Lavavej 的评论 on std::make_unsigned
and std::make_signed
.
因此,要么int8_t
是一个类型定义signed char
或者它是一个扩展的有符号整数类型,其对象恰好占用 8 位存储空间。
但是,要回答您的问题,您不应该做出假设。因为这两种形式的函数x.operator<<(y)
and operator<<(x,y)
已定义,§ 13.5.3 [over.binary] 表示我们参考 § 13.3.1.2 [over.match.oper] 来确定std::cout << i
。 § 13.3.1.2 反过来说,实现根据 § 13.3.2 和 § 13.3.3 从候选函数集中进行选择。然后,我们查看第 13.3.3.2 节 [over.ics.rank] 以确定:
- The
template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, signed char)
模板将被调用,如果int8_t
是完全匹配signed char
(即 typedef 为signed char
).
- 否则,
int8_t
将晋升为int
和basic_ostream<charT,traits>& operator<<(int n)
将调用成员函数。
如果是std::cout << u
for u
a uint8_t
object:
- The
template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, unsigned char)
模板将被调用,如果uint8_t
是完全匹配unsigned char
.
- 否则,既然
int
可以代表全部uint8_t
价值观,uint8_t
将晋升为int
和basic_ostream<charT,traits>& operator<<(int n)
将调用成员函数。
如果你总是想打印一个字符,最安全、最清晰的选择是:
std::cout << static_cast<signed char>(i);
如果你总是想打印一个数字:
std::cout << static_cast<int>(i);