c++ uint8_t无法使用cout打印

qrjkbowd  于 2023-07-01  发布在  其他
关注(0)|答案(8)|浏览(282)

我写了一个简单的程序,它将一个值设置为一个变量,然后打印它,但它并没有像预期的那样工作。我的程序只有两行代码:

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)
wh6knrhe

wh6knrhe1#

它实际上不会打印空白,但最有可能的是值为5的ASCII字符,这是不可打印的(或不可见的)。这里有很多invisible ASCII character codes,大多数都在值32以下,这实际上是空白的。
您必须将aa转换为unsigned int以输出数值,因为ostream& operator<<(ostream&, unsigned char)尝试输出可见字符值。

uint8_t aa=5;

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

yhived7q2#

在任何基元数据类型的变量之前添加一元+运算符将产生可打印的数值,而不是ASCII字符(对于char类型)。

uint8_t a = 5;
cout << "value is " << +a << endl; // value is 5

这是因为+a会导致a升级为int

cgh8pdjw

cgh8pdjw3#

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

ovfsdjhp

ovfsdjhp4#

  • 使用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)。
disbfnqx

disbfnqx5#

这是因为输出操作符将uint8_t视为charuint8_t通常只是unsigned char的别名),因此它使用ASCII代码(这是最常见的字符编码系统)5打印字符。
例如,参见this reference

gojuced7

gojuced76#

coutaa视为ASCII值5char,这是一个不可打印的字符,请尝试在打印前将其类型转换为int

c6ubokkw

c6ubokkw7#

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
bejyjqdl

bejyjqdl8#

正如其他人之前所说,出现问题是因为标准流将有符号字符和无符号字符视为单个字符而不是数字。
以下是我的解决方案,代码更改最少:

uint8_t aa = 5;

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

添加"+0"对任何数字都是安全的,包括浮点数。
对于整数类型,如果sizeof(aa) < sizeof(int),则将结果类型更改为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

pepper_chico和πάντα ε给出的ADL解决方案真的很漂亮。

相关问题