17

I was expecting the code: cout << uint8_t(0); to print 0, but it doesn't print anything.

When I try to stream uint8_t objects to cout, I get strange characters with gcc. Is this expected behavior? Could it be that uint8_t is an alias for some char-based type? See compiler/system notes below.

#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);
    }
}

Compiling and running it as follows:

g++ test-uint8.cpp -std=c++11 && ./a.out
  • using gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)
  • on the system Linux 3.7.9-101.fc17.x86_64

... produces the output:

>>>�<<<   >>>194<<<
>>><<<    >>>0<<<
>>><<<    >>>0<<<
>>><<<    >>>0<<<
>>><<<    >>>1<<<
>>><<<    >>>2<<<
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
John
  • 1,709
  • 1
  • 24
  • 27
  • Possible duplicate of [uint8\_t can't be printed with cout](https://stackoverflow.com/questions/19562103/uint8-t-cant-be-printed-with-cout) – phuclv Sep 03 '18 at 10:06
  • Does this answer your question? [cout uint8\_t as integers instead of chars](https://stackoverflow.com/questions/18246154/cout-uint8-t-as-integers-instead-of-chars) – phuclv Jun 30 '23 at 16:33

3 Answers3

18

uint8_t is an alias for unsigned char, and the iostreams have special overloads for chars that print out the characters rather than formatting numbers.

The conversion to integer inhibits this.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
7

Could it be that uint8_t is an alias for some char-based type?

Absolutely. It's required to be a typedef for a builtin 8-bit unsigned integral type, if such a type exists. Since there are only two possible 8-bit unsigned integral types, char for a compiler that treats it as unsigned and unsigned char, it must be one of those. Except on systems where char is larger than 8 bits, in which case it won't exist.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • +1 for pointing out that uint8_t may not exist! Didn't know that. – John Mar 08 '13 at 14:57
  • @Johann - for most uses, `uint_least8_t` is a better choice than `uint8_t`. – Pete Becker Mar 08 '13 at 14:59
  • 2
    An implementation is allowed to provide more extended integer types which are not aliases for the standard integer types. So I think technically `uint8_t` *could* be a non-character type, although it's usually not. – aschepler Mar 08 '13 at 15:00
  • @PeteBecker `uint_least8_t` didn't work, it's the same as `uint8_t `. – R1S8K May 25 '19 at 21:40
  • Yes, the C++ compiler treats it as `char`, where C compiler treats it as `unsigned char` which would output a numerical value. – R1S8K May 25 '19 at 21:41
  • 1
    @R1S8K `uint_least8_t` wouldn't work because it's almost certainly still `unsigned char`. The difference is that the `least` types are required to be there, while the *exact* size types are not. `uint_least8_t` is a better choice because it's guaranteed to exist, but not because it will work differently, though it may if it's not 8 bits. I assume you already figured this out given how old this comment is, but I figured this might help future readers :) – Will Eccles Apr 02 '21 at 19:29
  • @WillEccles I appreciate the comment anytime. But anyway the details along these types aren't clear to me right now because I'm mostly working in C for embedded programming. `uint8_t` is my most type of data for 8-bits. Thanks for the information. – R1S8K Apr 06 '21 at 18:06
  • @R1S8K I do embedded as well and can't really imagine a system where at least uint8_t (or a similar type) is not defined. In practice, I have never personally used a system where these types were not defined. Just thought I'd clarify for future readers :) – Will Eccles Apr 06 '21 at 18:38
  • @WillEccles — not my area, but I’ve heard that there are DSP chips where the smallest addressable storage is 16 (or even 32) bits, so no `uint8_t`. – Pete Becker Apr 06 '21 at 20:06
  • @WillEccles Yes they all are defined in `stdint.h` or `inttypes.h` and haven't thought of using `uint_least8_t`, does it have advantages over `uint8_t` ? – R1S8K Apr 06 '21 at 22:38
  • 1
    @R1S8K Not really, aside from the fact that it's actually required to exist. Most implementations will define the optional `uint8_t` anyway, if possible. C does not require that an implementation have a type that is exactly 8 bits, since it's possible that one might not. If you have `uint8_t`, you should use it. I see no reason why not. – Will Eccles Apr 08 '21 at 15:24
  • @WillEccles Yes, going back to the reason of this thread because my comment was long ago and based on my simple experience in C, the answers were of course deep enough for the thread question, but I think I wrote my comment thinking maybe I contributed to the thread, but I think I didn't pretty much. – R1S8K Apr 11 '21 at 16:48
0

As others have pointed out, uint8_t is streamed as an unsigned char. I've sometimes made use of bit fields from integer types that are streamed as, well, integers, to avoid having to cast or overload operator<<, but only when it doesn't waste space, like in the Pos struct below:

#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;
}

Output:

0
2
2
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • Why does using bit fields make the streamed values get interpreted as such instead of characters? Is this portable behaviour? – Ian Gralinski Mar 10 '20 at 03:31
  • 1
    @IanGralinski Because the underlaying type is an `unsigned short` for which numeric values is printed. Yes it's portable. – Ted Lyngmo Mar 10 '20 at 05:50