Why "Cout" Works Weird for "Unsigned Char"

Why cout works weird for unsigned char?

As you have commented, the reason is that you use cout to print its content directly. Here I will try to explain to you why this will not work.

cout << bottomRGB[0] << endl;

Why "cout" works weird for "unsigned char"?

It will not work because here bottomRGB[0] is a unsigned char (with value 218), cout actually will print some garbage value (or nothing) as it is just a non-printable ASCII character which is getting printed anyway. Note that ASCII character corresponding to 218 is non-printable. Check out here for the ASCII table.

P.S. You can check whether bottomRGB[0] is printable or not using isprint() as:

cout << isprint(bottomRGB[0]) << endl; // will print garbage value or nothing

It will print 0 (or false) indicating the character is non-printable


For your example, to make it work, you need to type cast it first before cout:

cout << (int) bottomRGB[0] << endl; // correctly printed (218 for your example) 

cout derefernced (unsigned char) pointers, gives me unexpected results

'8' is the character 8.
8 is just a code of a character which is invisible.

Try writing *buffer = 48; and guess why the output is "Buffer = 0" based on this table.

Cout unsigned char

The "sane" answer is: don't rely on extended-ASCII characters. Unicode is widespread enough to make this the preferred approach:

#include <iostream>
int main() {
std::cout << u8"\u00e0\n";
}

This will explicitly print the character à you requested; in fact, that's also how your browser understands it, which you can easily verify by putting into e.g. some unicode character search, which will result in LATIN SMALL LETTER A WITH GRAVE, with the code U+00E0 which you can spot in the code above.

In your example, there's no difference between using a signed or unsigned char; the byte value 133 gets written to the terminal, but the way it interprets it might differ from machine to machine, basing on how it's actually set up to interpret it. In fact, in a UTF-8 console, this is simply a wrong unicode sequence (u"\0x85" isn't a valid character) - if your OS was switched to UTF-8, that might be why you're seeing no output.

Garbage values when array declared as unsigned char

Because it's an unsigned char, std::cout is passing them to the terminal and it's being displayed as a character set (Well, attempting, anyway - the values are outside the range of valid printable characters for the character set you're using).

Cast to unsigned int when outputting with cout.

Sign & Unsigned Char is not working in C++

But C++ primer ... said it should work

No it doesn't. The quote from C++ primer doesn't use std::cout at all. The output that you see doesn't contradict with what the book says.

So I don't think they give the wrong information

No1.

did I do something wrong?

It seems that you've possibly misunderstood what the value of a character means, or possibly misunderstood how character streams work.

Character types are integer types (but not all integer types are character types). The values of unsigned char are 0..255 (on systems where size of byte is 8 bits). Each2 of those values represent some textual symbol. The mapping from a set of values to a set of symbols is called a "character set" or "character encoding".

std::cout is a character stream. << is stream insertion operator. When you insert a character into a stream, the behaviour is not to show the numerical value. Instead, the behaviour to show the symbol that the value is mapped to3 in the character set that your system uses. In this case, it appears that the value 255 is mapped to whatever strange symbol you saw on the screen.

If you wish to print the numerical value of a character, what you can do is convert to a non-character integer type and insert that to the character stream:

int i = c;
std::cout << i;

1 At least, there's no wrong information regarding your confusion. The quote is a bit inaccurate and outdated in case of c2. Before C++20, the value was "implementation defined" rather than "undefined". Since C++20, the value is actually defined, and the value is 0 which is the null terminator character that signifies end of a string. If you try to print this character, you'll see no output.

2 This was bit of a lie for simplicity's sake. Some characters are not visible symbols. For example, there is the null terminator charter as well as other control characters. The situation becomes even more complex in the case of variable width encodings such as the ubiquitous Unicode, where symbols may consist of a sequence of several char. In such encoding, and individual char cannot necessarily be interpreted correctly without other char that are part of such sequence.

3 And this behaviour should feel natural once you grok the purpose of character types. Consider following program:

unsigned char c = 'a';
std::cout << c;

It would be highly confusing if the output would be a number that is the value of the character (such as 97 which may be the value of the symbol 'a' on the system) rather than the symbol 'a'.


For extra meditation, think about what this program might print (and feel free to try it out):

char c = 57;
std::cout << c << '\n';

int i = c;
std::cout << i << '\n';

c = '9';
std::cout << c << '\n';

i = c;
std::cout << i << '\n';

uint8_t can't be printed with cout

It doesn't really print a blank, but most probably the ASCII character with value 5, which is non-printable (or invisible). There's a number of invisible ASCII character codes, most of them below value 32, which is the blank actually.

You have to convert aa to unsigned int to output the numeric value, since ostream& operator<<(ostream&, unsigned char) tries to output the visible character value.

uint8_t aa=5;

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


Related Topics



Leave a reply



Submit