187

我有一个关于在 C++ 中使用整数的奇怪问题。

我编写了一个简单的程序,它为变量设置一个值,然后打印它,但它没有按预期工作。

我的程序只有两行代码:

uint8_t aa = 5;

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

这个程序的输出是value is

即,它为aa.

当我更改uint8_tuint16_t上面的代码时,它就像一个魅力。

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

gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
4

8 回答 8

202

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

您必须转换aaunsigned int输出数值,因为ostream& operator<<(ostream&, unsigned char)尝试输出可见字符值。

uint8_t aa=5;

cout << "value is " << unsigned(aa) << endl;
于 2013-10-24T09:32:56.050 回答
55

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

于 2013-10-24T09:33:11.627 回答
53

在任何原始数据类型的变量之前添加一元 + 运算符将给出可打印的数值而不是 ASCII 字符(在 char 类型的情况下)。

uint8_t aa = 5;
cout<<"value is "<< +aa <<endl; // value is 5
于 2015-08-13T14:58:59.193 回答
20
  • 使用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)。
于 2014-01-27T19:26:34.643 回答
18

这是因为输出运算符将uint8_ta char(uint8_t通常只是 的别名unsigned char) 视为,因此它使用 ASCII 码(这是最常见的字符编码系统)打印字符5

参见例如this reference

于 2013-10-24T09:33:29.350 回答
8

cout将ASCII 值aa视为不可打印字符,请在打印前尝试进行类型转换。char5int

于 2013-10-24T09:33:44.440 回答
6

和之间的operator<<()重载是一个非成员函数。您可以显式使用成员函数将 a (或 a )视为。std::ostreamcharcharuint8_tint

#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
于 2015-11-17T18:40:48.370 回答
2

正如其他人在问题发生之前所说的那样,因为标准流将有符号字符和无符号字符视为单个字符而不是数字。

这是我的代码更改最少的解决方案:

uint8_t aa = 5;

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

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

对于整数类型,它会将结果类型更改为intif sizeof(aa) < sizeof(int)。并且它不会改变类型 if 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 的 PS 解决方案真的很漂亮。

于 2015-06-29T06:49:11.533 回答