问题
It seems so strange. I found misunderstanding. I use gcc with char as signed char. I always thought that in comparison expressions(and other expressions) signed value converts to unsigned if necessary.
int a = -4;
unsigned int b = a;
std::cout << (b == a) << std::endl; // writes 1, Ok
but the problem is that
char a = -4;
unsigned char b = a;
std::cout << (b == a) << std::endl; // writes 0
what is the magic in comparison operator if it's not just bitwise?
回答1:
According to the C++ Standard
6 If both operands are of arithmetic or enumeration type, the usual arithmetic conversions are performed on both operands; each of the operators shall yield true if the specified relationship is true and false if it is false.
So in this expression
b == a
of the example
char a = -4;
unsigned char b = -a;
std::cout << (b == a) << std::endl; // writes 0
the both operands are converted to type int
. As the result signed char propagets its signed bit and two values become unequal.
To demonstrate the effect try to run this simple example
{
char a = -4;
unsigned char b = -a;
std::cout << std::hex << "a = " << ( int )a << "'\tb = " << ( int )b << std::endl;
if ( b > a ) std::cout << "b is greater than a, that is b is positive and a is negative\n";
}
The output is
a = fffffffc' 'b = 4
b is greater than a, that is b is positive and a is negative
Edit: Only now I have seen that definitions of the variables have to look as
char a = -4;
unsigned char b = a;
that is the minus in the definition of b ahould not be present.
回答2:
Since an (unsigned) int
is at least 16 bits wide, let's use that for instructional purposes:
In the first case: a = 0xfffc
, and b = (unsigned int) (a) = 0xfffc
Following the arithmetic conversion rules, the comparison is evaluated as:
((unsigned int) b == (unsigned int) a)
or (0xfffc == 0xfffc)
, which is (1)
In the 2nd case: a = 0xfc
, and b = (unsigned char) ((int) a)
or:
b = (unsigned char) (0xfffc) = 0xfc
i.e., sign-extended to (int)
and truncated
Since and int
can represent the range of both the signed char
and unsigned char
types, the comparison is evaluated as: (zero-extended vs. sign-extended)
((int) b == (int) a)
or (0x00fc == 0xfffc)
, which is (0)
.
Note: The C and C++ integer conversion rules behave the same way in these cases. Of course, I'm assuming that the char
types are 8 bit, which is typical, but only the minimum required.
回答3:
They both output 0 because unsigned values can get converted to signed values, not viceversa (like you said).
来源:https://stackoverflow.com/questions/21027305/comparison-signed-and-unsigned-char