1

I was under the impression that both would be set to different values but all three of these things are outputting the exact same character. Is there some kind of implicit conversion going on or what?

unsigned char unsc1 = 128;
std::cout << "Unsigned Char 1 = " << unsc1 << std::endl;


signed char sc1 = 128;
std::cout << "Signed Char 1 = " << sc1 << std::endl;



char c1 = 128;
std::cout << "Char 1 = " << c1 << std::endl;

The same thing happens when both are set to 254, it was my understanding that a signed variable type shouldn't be able to hold as much data as one that was unsigned.

Propagating
  • 130
  • 1
  • 13

3 Answers3

3

Both signed and unsigned characters would be interpreted as char when you send it to cout unchanged. If you would like to see different results, cast these values to int before printing:

unsigned char unsc1 = 128;
std::cout << "Unsigned Char 1 = " << (int)unsc1 << std::endl;


signed char sc1 = 128;
std::cout << "Signed Char 1 = " << (int)sc1 << std::endl;

Now on probably all extant platforms the signed char would print -128, while unsigned one would print 128 (according to the standard, chapter 4.7, section 3, it is implementation-defined).

(demo on ideone).

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    The second is UB when `CHAR_BIT` is 8 IIRC. I'm pretty sure initialization "overflow" counts, right? – chris Jun 30 '14 at 00:02
  • @chris I need to check the standard, but I think you're right. – Sergey Kalinichenko Jun 30 '14 at 00:03
  • I see the different results now, and the -128 is expected. Did they change that at some point in C++? I was under the impression that when you set a Char to a value that it would return the appropriate character associated with that value. – Propagating Jun 30 '14 at 00:05
  • 2
    @dasblinkenlight, I think I was wrong and it's implemnetation-defined per §4.7 [conv.integral]/3. – chris Jun 30 '14 at 00:10
  • 1
    @chris: That's right - conversion from unsigned to signed is implementation defined, but signed *overflow* (i.e. the result of an arithmetic operation) is undefined. – Kerrek SB Jun 30 '14 at 00:12
  • 1
    @chris You-re right - I just found the 4.7.3 part myself ("If the destination type is signed, the value is unchanged if it can be represented in the destination type (and bit-field width); otherwise, the value is implementation-defined.") – Sergey Kalinichenko Jun 30 '14 at 00:14
  • @dasblinkenlight: instead of me editing more, let me just mention that [some Texas Instruments digital signal processors have 16-bit `char`](http://stackoverflow.com/questions/6971886/exotic-architectures-the-standards-committees-care-about). I forgot to mention the byte size in my edit. Also, that the unsigned result is guaranteed (regardless of platform). – Cheers and hth. - Alf Jun 30 '14 at 00:35
  • @Cheersandhth.-Alf, Cool, thanks for that link. It's a lot nicer when you actually have a real example. – chris Jun 30 '14 at 00:56
0

As we know, 128 is not a printable ASCII code. So none of your three statements will get a character. At least in my environment, gcc version 4.1.2, libc6,x86-64

where23
  • 483
  • 3
  • 9
  • Be aware that there is a wide variety of possibilities for the character with code 128. For example, in Windows 1252, it is €. In UTF-8, it is a control character. – chris Jun 30 '14 at 00:25
0

I don't think this is correct:


signed char sc1 = 128;  // overflow.

You seem to try something resulting kind of 'undefined behavior'.

ALittleDiff
  • 1,191
  • 1
  • 7
  • 24
  • If you haven't seen it, http://stackoverflow.com/questions/24481322/why-does-an-unsigned-char-return-the-same-value-as-a-signed-char-in-c#comment37893875_24481359 – chris Jun 30 '14 at 00:20