提问人:CoderInNetwork 提问时间:10/24/2013 最后编辑:Jan SchultkeCoderInNetwork 更新时间:9/5/2023 访问量:148464
uint8_t不能用 cout 打印
uint8_t can't be printed with cout
问:
我编写了一个简单的程序,将值设置为变量,然后打印它,但它没有按预期工作。我的程序只有两行代码:
uint8_t a = 5;
cout << "value is " << a << endl;
该程序的输出是 ,即它为 打印空白。value is
a
当我更改为 时,上面的代码就像一个魅力。uint8_t
uint16_t
我使用 Ubuntu 12.04 (Precise Pangolin),64 位,我的编译器版本是:
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
答:
它并没有真正打印空白,但很可能是值为 5 的 ASCII 字符,该字符是不可打印(或不可见)的。有许多不可见的 ASCII 字符代码,其中大多数低于值 32,这实际上是空白。
您必须转换为才能输出数值,因为尝试输出可见字符值。a
unsigned int
ostream& operator<<(ostream&, unsigned char)
uint8_t a = 5;
cout << "value is " << unsigned(a) << endl;
评论
int
+aa
int(var)
(int)var
int(var)
(int)var
static_cast
uint8_t
很可能是 for .该类有一个特殊的重载 ,即它打印带有数字 5 的字符,这是不可打印的,因此是空白的。typedef
unsigned char
ostream
unsigned char
评论
这是因为输出运算符将 a 视为 (通常只是 的别名),因此它使用 ASCII 代码(这是最常见的字符编码系统)打印字符。uint8_t
char
uint8_t
unsigned char
5
例如,请参阅此参考资料。
评论
signed
unsigned
char
uint8_t
unsigned char
cout
被视为 ASCII 值,这是一个不可打印的字符,请在打印前尝试排版。aa
char
5
int
评论
利用 ADL(与参数相关的名称查找):
#include <cstdint> #include <iostream> #include <typeinfo> namespace numerical_chars { inline std::ostream &operator<<(std::ostream &os, char c) { return std::is_signed<char>::value ? os << static_cast<int>(c) : os << static_cast<unsigned int>(c); } inline std::ostream &operator<<(std::ostream &os, signed char c) { return os << static_cast<int>(c); } inline std::ostream &operator<<(std::ostream &os, unsigned char c) { return os << static_cast<unsigned int>(c); } } int main() { using namespace std; uint8_t i = 42; { cout << i << endl; } { using namespace numerical_chars; cout << i << endl; } }
输出:
* 42
自定义流操纵器也是可能的。
- 一元加号运算符也是一个简洁的成语()。
cout << +i << endl
评论
return std::is_signed<char>::value ? os << static_cast<int>(c) : os << static_cast<unsigned int>(c);
正如其他人之前所说,之所以会出现问题,是因为标准流将有符号字符和无符号字符视为单个字符,而不是数字。
这是我的解决方案,代码更改最少:
uint8_t aa = 5;
cout << "value is " << aa + 0 << endl;
任何数字(包括浮点数)的加法都是安全的。"+0"
对于整数类型,它会将结果类型更改为 if 。如果 .int
sizeof(aa) < sizeof(int)
sizeof(aa) >= sizeof(int)
此解决方案也适用于准备打印以流式传输,而其他一些解决方案则不太好:int8_t
int8_t aa = -120;
cout << "value is " << aa + 0 << endl;
cout << "bad value is " << unsigned(aa) << endl;
输出:
value is -120
bad value is 4294967176
P.S. pepper_chico 和 πάντα ῥεῖ 给出的 ADL 解决方案真的很漂亮。
评论
在任何基元数据类型的变量之前添加一元 + 运算符将产生可打印的数值,而不是 ASCII 字符(如果是 char 类型)。
uint8_t a = 5;
cout << "value is " << +a << endl; // value is 5
这之所以有效,是因为结果被提升为 int
。+a
a
评论
uint8_t
unsigned char
uint8_t
unsigned char
unsigned char
ostream
char
unsigned char
int
short int
long
int
和之间的重载是非成员函数。可以显式使用 member 函数将 (或 ) 视为 .operator<<()
std::ostream
char
char
uint8_t
int
#include <iostream>
#include <cstddef>
int main()
{
uint8_t aa=5;
std::cout << "value is ";
std::cout.operator<<(aa);
std::cout << std::endl;
return 0;
}
输出:
value is 5
这是 iostream 的已知问题之一,iostream 将 (通常是 的别名 ) 解释为代码单元而不是整数类型。它已在 C++20 std::格式
中修复。例如 (godbolt):unsigned char
uint8_t
unsigned char
uint8_t a = 5;
std::cout << std::format("value is {}\n", a);
指纹
value is 5
在 C++23 中,这可以进一步简化为:
uint8_t a = 5;
std::print("value is {}\n", a);
免责声明:我是 C++20 和 C++23 的作者。std::format
std::print
上一个:什么是透明比较器?
下一个:为什么枚举类优先于普通枚举?
评论