4

Why are two char like signed char and unsigned char with the same value not equal?

char a = 0xfb; 
unsigned char b = 0xfb;
bool f;
f = (a == b); 
cout << f;

In the above code, the value of f is 0.
Why it's so when both a and b have the same value?

Beyondo
  • 2,952
  • 1
  • 17
  • 42
T.g
  • 169
  • 2
  • 11
  • have u seen this warning in your compiler? `warning: overflow in conversion from 'int' to 'char' changes value from '251' to ''\37777777773'' [-Woverflow] char a=0xfb;` [see here](http://coliru.stacked-crooked.com/a/b83589f0c4bb883e). – pergy Aug 08 '18 at 14:30
  • My code is running without any warning & giving output as 0; – T.g Aug 08 '18 at 14:36
  • Try enabling warnings. The value of `a` is `-5`. The value of `b` is `251`. They are not equal. – Raymond Chen Aug 08 '18 at 14:40
  • @raymondChen a is -5 -> a is probably -5 – Bathsheba Aug 08 '18 at 14:41
  • @Bathsheba The likelihood that OP is using a ones-complement or sign-magnitude system is vanishingly small. – Raymond Chen Aug 08 '18 at 14:43
  • @RaymondChen: Or non-existent in C++14! But note that the conversion is still implementation defined. – Bathsheba Aug 08 '18 at 14:44
  • 1
    @Bathsheba I think it's not helpful to the OP to get into language-lawyering details. Let's try to explain the observed behavior. – Raymond Chen Aug 08 '18 at 14:45
  • @RaymondChen: I think you can do both in this case. My answer is hardly technical, no? – Bathsheba Aug 08 '18 at 14:46
  • The number of systems where `CHAR_MAX` is not 127 and integers are not twos-complement is basically zero. No need to inject the possibility into a beginner discussion. – Raymond Chen Aug 08 '18 at 14:52
  • 2
    @RaymondChen: Rubbish. It's appropriate here to have a selection of answers. I really don't see your point. Do not (i) make assumptions about the OP and (ii) don't assume this entire page is targetted at the OP. And your comment above is ignorant. I have access to a machine where char, short, int, long, and long long are all the same size. – Bathsheba Aug 08 '18 at 14:54
  • @Bathsheba: I'm curious. Is it a DSP? – geza Aug 08 '18 at 21:16

3 Answers3

8

There are no arithmetic operators that accept integers smaller than int. Hence, both char values get promoted to int first, see integral promotion for full details.

char is signed on your platform, so 0xfb gets promoted to int(-5), whereas unsigned char gets promoted to int(0x000000fb). These two integers do not compare equal.

On the other hand, the standard in [basic.fundamental] requires that all char types occupy the same amount of storage and have the same alignment requirements; that is, they have the same object representation and all bits of the object representation participate in the value representation. Hence, memcmp(&a, &b, 1) == 0 is true.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
6

The value of f and, in fact, the behaviour of the program, is implementation-defined.

In C++14 onwards1, for a signed char, and assuming that CHAR_MAX is 127, a will probably be -5. Formally speaking, if char is signed and the number does not fit into a char, then the conversion is implementation-defined or an implementation-defined signal is raised.

b is 251.

For the comparison a == b (and retaining the assumption that char is a narrower type than an int) both arguments are converted to int, with -5 and 251 therefore retained.

And that's false as the numbers are not equal.

Finally, note that on a platform where char, short, and int are all the same size, the result of your code would be true (and the == would be in unsigned types)! The moral of the story: don't mix your types.


1 C++14 dropped 1's complement and signed magnitude signed char.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
4
  • Value range for (signed) char is [-128, 127]. (C++14 drops -127 as the lower range).
  • Value range for unsigned char is [0, 255]

What you're trying to assign to both of the variables is 251 in decimal. Since char cannot hold that value you will suffer a value overflow, as the following warning tells you.

warning: overflow in conversion from 'int' to 'char' changes value from '251' to ''\37777777773'' [-Woverflow]

As a result a will probably hold value -5 while b will be 251 and they are indeed not equal.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
pergy
  • 5,285
  • 1
  • 22
  • 36
  • But at output both a and b are printing same symbol. – T.g Aug 08 '18 at 14:39
  • @T.g The printing mechanism for character types interprets the underlying bit pattern, not the numerical value of the variable. The representation is the same, but the values are different. – molbdnilo Aug 08 '18 at 14:46
  • @molbdnilo thanks, I got it...but how the value -5 is assigned to a ..since 251 is not in range of [-128,127] – T.g Aug 08 '18 at 18:01
  • @T.g I've just asked the same under the other answer :) take a look at this: https://stackoverflow.com/a/1049880/509868 – pergy Aug 08 '18 at 18:08