26

I am working on below code:

#include<iostream>
#include<stdio.h>

using namespace std;

main() {
    unsigned char a;
    a=1;
    printf("%d", a);
    cout<<a;
}

It is printing 1 and some garbage.

Why cout is behaving so?

phuclv
  • 37,963
  • 15
  • 156
  • 475
Hitesh Menghani
  • 977
  • 1
  • 6
  • 14
  • 2
    An `unsigned char` is not an `int`. Why are you telling `printf` it is? – chris Mar 23 '13 at 09:39
  • What would you expect from sending a binary 1 to stout? – Udo Klein Mar 23 '13 at 09:40
  • 2
    @chris `unsigned char` will be promoted to `unsigned` in a printf call, so the code is acceptable. – john Mar 23 '13 at 10:14
  • @john, Ah, silly me. I thought there was one for unsigned char because of the char one, but that just ends up making no sense really. Thanks for clearing it up. – chris Mar 23 '13 at 10:22
  • the 32 first character codes are control codes and are non-printable – phuclv Jun 24 '14 at 04:27
  • Possible duplicate of [how do I print an unsigned char as hex in c++ using ostream?](http://stackoverflow.com/questions/673240/how-do-i-print-an-unsigned-char-as-hex-in-c-using-ostream) – Alex Lop. May 18 '16 at 10:12
  • seems to work now. now its just std::cout printing garbage if it gets a uint8_t.`std::cout << (uint8_t)3 << std::endl` prints a heart, even though clearly the proper representation for a byte with value 3 is not a heart, unless its a signed byte, then it would be reasonable. – Dmytro Dec 07 '16 at 19:13

6 Answers6

41

cout << a is printing a value which appears to be garbage to you. It is not garbage actually. It is just a non-printable ASCII character which is getting printed anyway. Note that ASCII character corresponding to 1 is non-printable. You can check whether a is printable or not using, std::isprint as:

std::cout << std::isprint(a) << std::endl;

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

--

Anyway, if you want your cout to print 1 also, then cast a to this:

cout << static_cast<unsigned>(a) << std::endl;
Michael Rader
  • 5,839
  • 8
  • 33
  • 43
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • How about printing signed char in C++ using cout? What is expected and how it is defined? For eg: signed char a=-50; cout< – Rajesh Jan 16 '18 at 03:56
  • This works but I'm wondering why? Shouldn't it be `unsigned int` rather than just `unsigned`? Because the `unsigned` keyword can be used with either `int` or `float` or any other in-built data types, right? – Milan Sep 09 '20 at 20:08
  • 1
    @Milan: `unsigned` is translated by compiler to be `unsigned int`. – Nawaz Sep 10 '20 at 13:42
  • I prefer the unary plus operator over an explicit cast: `std::cout << +a << '\n';` – Cody Gray - on strike Oct 23 '21 at 07:03
15

I had a similar issue here that I've long forgotten about. The resolution to this problem with iostream's cout can be done like this:

#include<iostream>
#include<stdio.h>

main() {
    unsigned char a;
    a=1;
    printf("%d", a);
    std::cout<< +a << std::endl;

    return 0;
}

instead of casting it back to another type if you want cout to print the unsigned char value as opposed to the ascii character. You need to promote it.

If you noticed all I did was add a + before the unsigned char. This is unary addition that will promote the unsigned char to give you the actual number representation.

User Baum mit Augen is responsible for reminding me of this solution.

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
4

You need to typecast a as integer as cout<< (int)(a);. With this you will observe 1 on the output. With cout << a;, the print will be SOH (Start of Heading) corresponding to ascii value of 1 which can't be printed and hence, some special character is observed.

EDIT:

To be more accurate, the cout statement should be cout << static_cast<unsigned>(a) as Nawaz has mentioned.

Ganesh
  • 5,880
  • 2
  • 36
  • 54
3

The C compiler has its own way of defining the type of the printed output, because you can specify the type of the output.

Ex:

uint8_t c = 100;
printf("%d",c);

so you can also print c as an int by %d, or char %c, string %s or a hex value %x.

Where C++ has its own way too, the cout prints the 8-bit values as a char by default. So, you have to use specifiers with the output argument.

You can either use:

  1. a + before the name of the output argument

    uint8_t data_byte = 100;
    cout << "val: " << +data_byte << endl;
    
  2. use a function cast unsigned(var); like,

     uint8_t data_byte = 100;
     cout << "val: " << unsigned(data_byte) << endl;
    
R1S8K
  • 365
  • 1
  • 3
  • 18
0

A char will have a numerical value associated with it. The character represented by 1 is the SOH or Start of header character which is usually not printed (similar to printing the NUL character \0).

You can have a look at an ASCII table to see which character will be printed, but an example with a value such as 65 might help. Where 65 is the A characater.

#include<iostream>
#include<stdio.h>


int main() {
    // initialise with an integer
    char a = 65;

    // print the integer representation
    printf("%d\n", a);

    // print as a character
    std::cout << a << std::endl;

    // initialise with a character 
    char b = 'B';

    // print the integer representation
    printf("%d\n", b);
    std::cout << static_cast<int>(b) << std::endl;
    
    // print as a character
    std::cout << b << std::endl;
}

Outputs:

65
A
66
66
B
0RR
  • 1,538
  • 10
  • 21
-3

printf("%u",a); its so simple try it

  • Could you explain your answer a bit more? – Charlie May 18 '16 at 05:33
  • Although this code may answer the question, providing additional context regarding _why_ and/or _how_ it answers the question would significantly improve its long-term value. Please [edit] your answer to add some explanation. In particular, please explain why you think that `%u` is better than `%hhu` for an `unsigned char` argument. – Toby Speight May 18 '16 at 12:02
  • And this does nothing at all to address the question (why does `cout::operator<<(unsigned char)` interpret its argument as a character rather than as an arithmetic value?) – Toby Speight May 18 '16 at 12:04