Uint8_t不能用cout打印

我有一个关于在c++中处理整数的奇怪问题。

我写了一个简单的程序,将一个值设置为一个变量,然后打印它,但它不像预期的那样工作。

我的程序只有两行代码:

uint8_t aa = 5;


cout << "value is " << aa << endl;

这个程序的输出是value is

也就是说,它为aa打印空白。

当我把uint8_t改为uint16_t时,上面的代码就像一个魔法一样。

我使用64位的ubuntu 12.04 (Precise Pangolin),我的编译器版本是:

gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
127923 次浏览

它并不真正打印一个空白,但很可能是值为5的ASCII字符,这是不可打印的(或不可见的)。有一些不可见ASCII字符码,其中大多数低于值32,这实际上是空白。

你必须将aa转换为unsigned int来输出数值,因为ostream& operator<<(ostream&, unsigned char)试图输出可见的字符值。

uint8_t aa=5;


cout << "value is " << unsigned(aa) << endl;

uint8_t很可能是unsigned chartypedefostream类对unsigned char有一个特殊的重载,即它打印带有数字5的字符,这是不可打印的,因此是空白。

这是因为输出操作符将uint8_t视为char (uint8_t通常只是unsigned char的别名),所以它用ASCII码(这是最常见的字符编码系统)5打印字符。

参见e.g. 这个引用

coutaa处理为ASCII值5char,这是一个不可打印的字符,在打印之前尝试类型转换为int

  • 使用诽谤联盟(依赖参数的名称查找):

    #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
    
  • A custom stream manipulator would also be possible.

  • The unary plus operator is a neat idiom too (cout << +i << endl).

正如其他人之前所说,问题发生是因为标准流将signed char和unsigned char视为单个字符,而不是数字。

以下是我对代码修改最少的解决方案:

uint8_t aa = 5;


cout << "value is " << aa + 0 << endl;

添加"+0"对包括浮点数在内的任何数字都是安全的。

对于整数类型,如果sizeof(aa) < sizeof(int). 0,则将结果类型更改为int。如果sizeof(aa) >= sizeof(int). conf,它将不会改变类型。

这个解决方案也适用于准备将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 aa = 5;
cout<<"value is "<< +aa <<endl; // value is 5

std::ostreamchar之间的operator<<()重载是非成员函数。可以显式地使用成员函数将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