Casting from `int` to `unsigned char`

user4063326 picture user4063326 · Oct 31, 2014 · Viewed 25.9k times · Source

I am running the following C++ code on Coliru:

#include <iostream>
#include <string>

int main()
{
     int num1 = 208;
     unsigned char uc_num1 = (unsigned char) num1;
     std::cout << "test1: " << uc_num1 << "\n";

     int num2 = 255;
     unsigned char uc_num2 = (unsigned char) num2;
     std::cout << "test2: " << uc_num2 << "\n";
}

I am getting the output:

test1: �

test2: �

This is a simplified example of my code.

Why does this not print out:

test1: 208

test2: 255

Am I misusing std::cout, or am I not doing the casting correctly?


More background

I want to convert from int to unsigned char (rather than unsigned char*). I know that all my integers will be between 0 and 255 because I am using them in the RGBA color model.

I want to use LodePNG to encode images. The library in example_encode.cpp uses unsigned chars in std::vector<unsigned char>& image:

//Example 1
//Encode from raw pixels to disk with a single function call
//The image argument has width * height RGBA pixels or width * height * 4 bytes
void encodeOneStep(const char* filename, std::vector<unsigned char>& image, unsigned width, unsigned height)
{
  //Encode the image
  unsigned error = lodepng::encode(filename, image, width, height);

  //if there's an error, display it
  if(error) std::cout << "encoder error " << error << ": "<< lodepng_error_text(error) << std::endl;
}

Answer

Eric picture Eric · Oct 31, 2014

std::cout is correct =)

Press ALT then 2 0 8 This is the char that you are printing with test1. The console might not know how to print that properly so it outputs the question mark. Same thing with 255. After reading the png and putting it in the std::vector, there is no use of writing it to the screen. This file contains binary data which is not writable.

If you want to see "208" and "255", you should not convert them to unsigned char first, or specify that you want to print numbers such as int for example, like this

std::cout << num1 << std::endl;
std::cout << (int) uc_num1 << std::endl;

You are looking at a special case of std::cout which is not easy to understand at first.

When std::cout is called, it checks the type of the right hand side operand. In your case, std::cout << uc_num1 tells cout that the operand is an unsigned char, so it does not perform a conversion because unsigned char are usually printable. Try this :

unsigned char uc_num3 = 65;
std::cout << uc_num3 << std::endl;

If you write std::cout << num1, then cout will realize that you are printing an int. It will then transform the int into a string and print that string for you.

You might want to check about c++ operator overloading to understand how it works, but it is not super crucial at the moment, you just need to realize that std::cout can behave differently for different data type you try to print.