3

I am currently working on a more complex program, and I came across a very weird syntax error best demonstrated with the following minimal example:

#include <iostream>

int main(int argc, char *argv[]){
        char c = 1 + '0';
        std::cout << 1 + '0' << std::endl;
        std::cout << c << std::endl;
        std::cout << '0' + 1 << std::endl;
        return 1;
}

This example produces the following output:

$ ./program
49
1
49

What appears to be happening here is that when the conversion from a single digit integer expression to a character happens outside a stream statement, it succeeds, but when it happens inside such a statement, it produces a garbage answer.

I tried to find someone else asking something similar on Google, but I can't find anything relevant.

I am using g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 on Ubuntu 16.04 LTS x64, but the issue occurs in clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final) as well, which rules out a compiler bug.

john01dav
  • 1,842
  • 1
  • 21
  • 40

2 Answers2

7

The result of a int + char is an int. So when you do

char c = 1 + '0';

You actually get

char c = 49;

And now c has the value of 49. When yo go to print that though, cout's operator << is overloaded to take a char and instead of displaying 49 it will display the character that 49 represents.

When you do

std::cout << 1 + '0' << std::endl;

Since 1 + '0' is an int you get the int overload of operator << which just outputs the integer 49.


It should be noted that anything smaller than an int will be promoted to an int when doing arithmetic operations. That means that, char + char, short + short, char + short, ..., will all be an int so even doing something like

std::cout << static_cast<char>(1) + '0' << std::endl;

Will still give you a integer output. You have to cast the result back to a char to get a char like

std::cout << static_cast<char>(1 + '0') << std::endl;
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • When I change the first cout statement to `std::cout << static_cast(1) + '0' << std::endl;` the output remains unchanged, despite the fact it is now a char + char = char statement, so it should use the overload of `operator<<` for a char. Why? – john01dav Apr 04 '18 at 15:29
  • @john01dav Change it to `static_cast(1 + '0')`. – Hatted Rooster Apr 04 '18 at 15:30
  • @john01dav Anything that is smaller than an `int` is promoted to an `int` when doing operations to it. So `char + char`, `short + short`, `char + short`, ... will all be an `int` – NathanOliver Apr 04 '18 at 15:30
  • @NathanOliver Thanks! Although can I recommend that as a good addition to the answer for future readers? – john01dav Apr 04 '18 at 15:31
0

but when it happens inside such a statement, it produces a garbage answer.

No.

char c = 1 + '0';
std::cout << c << std::endl;

In this case the rvalue int is implicitly converted to char. Then the char overload is used with std::cout, resulting in '1' as ASCII.


std::cout << 1 + '0' << std::endl;

In this case you're printing out the integer right away, so the integer overload is picked, this prints the numeric value of the '1' which is 49.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122