iostream行为

17
我原本期望这段代码:cout << uint8_t(0);会打印出0,但实际上它什么都没打印出来。
当我尝试将uint8_t对象输出到cout时,使用gcc编译器会得到一些奇怪的字符。这是预期的行为吗?可能是因为uint8_t是某种基于char的类型的别名吗?请参考下面的编译器/系统说明。
#include <cstdint>
#include <iostream>

void print(const uint8_t& n)
{
    std::cout << ">>>" << n                 << "<<<    "
              << ">>>" << (unsigned int)(n) << "<<<\n";
}

int main()
{
    uint8_t a;
    uint8_t b(0);
    uint8_t c = 0;
    uint8_t d{0};
    uint8_t e = 1;
    uint8_t f = 2;

    // Note that the first print statement uses an unset uint8_t
    // and therefore the behaviour is undefined. (Included here for
    // completeness)
    for (auto i : {a, b, c, d, e, f})
    {
        print(i);
    }
}

编译并运行如下:
g++ test-uint8.cpp -std=c++11 && ./a.out

使用 `gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)` 在系统 `Linux 3.7.9-101.fc17.x86_64` 上,产生输出:
>>>�<<<   >>>194<<<
>>><<<    >>>0<<<
>>><<<    >>>0<<<
>>><<<    >>>0<<<
>>><<<    >>>1<<<
>>><<<    >>>2<<<

可能是重复问题:uint8_t无法使用cout打印 - phuclv
这个回答解决了你的问题吗?将uint8_t作为整数而不是字符输出 - phuclv
3个回答

18

uint8_tunsigned char的别名,iostreams在处理字符时具有特殊的重载,可以打印出字符而不是格式化数字。

转换为整数会阻止这种行为。


7

uint8_t是不是char类型的别名?

完全正确。如果存在这样的内置8位无符号整数类型,则必须将其定义为typedef。由于只有两种可能的8位无符号整数类型,对于将其视为无符号的编译器来说是charunsigned char,因此它必须是其中之一。除非在char大于8位的系统上,否则它不存在。


2
一种实现允许提供更多不是标准整数类型别名的扩展整数类型。因此,我认为从技术上讲,uint8_t 可以是非字符类型,尽管通常不是这样。 - aschepler
1
@R1S8K uint_least8_t 不会起作用,因为它几乎肯定仍然是 unsigned char。区别在于 least 类型是必须存在的,而 exact 大小类型不是。uint_least8_t 是一个更好的选择,因为它保证存在,但不是因为它会有不同的作用,尽管如果它不是 8 位可能会有所不同。我假设你已经发现了这一点,考虑到这条评论的年代,但我想这可能会帮助未来的读者 :) - Will Eccles
@WillEccles 我随时感谢您的评论。但是,由于我主要从事嵌入式编程中的C语言开发,所以目前这些类型的细节对我来说并不清楚。uint8_t是我处理8位数据的最常用类型。感谢您提供的信息。 - R1S8K
@R1S8K 我也从事嵌入式开发,很难想象一个没有定义至少uint8_t(或类似类型)的系统。实际上,我从未亲自使用过这些类型未定义的系统。只是想为未来的读者澄清一下 :) - Will Eccles
1
@R1S8K 其实不是这样的,除了它确实需要存在之外。大多数实现都会定义可选的 uint8_t,如果可能的话。C语言并不要求实现具有恰好8位的类型,因为可能没有这样的类型。如果你有 uint8_t,你应该使用它。我看不出为什么不用。 - Will Eccles
显示剩余7条评论

0

正如其他人指出的那样,uint8_t 被流式传输为 unsigned char。有时我会利用从整数类型中提取的位域,这些位域被流式传输为整数,以避免强制转换或重载 operator<<,但仅当它不浪费空间时,比如在下面的 Pos 结构体中:

#include <iostream>

struct WasteAbyte {
    unsigned short has_byte_range:8;
};

struct Pos {
    unsigned short x:8;
    unsigned short y:8;
};

int main() {
    WasteAbyte W = {255};

    ++W.has_byte_range;

    std::cout << W.has_byte_range << std::endl;

    std::cout << sizeof(WasteAbyte) << std::endl;
    std::cout << sizeof(Pos) << std::endl;

    return 0;
}

输出:

0
2
2

为什么使用位域会使流式值被解释为这样的值而不是字符?这是可移植的行为吗? - Ian Gralinski
1
@IanGralinski 因为底层类型是“unsigned short”,可以打印数值。是的,它是可移植的。 - Ted Lyngmo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接