I have the following C code:
a = (b == B1) ? A1 : A2;
a, b, A1, A2 and B1 are all of type unsigned char. A1, A2 and B1 are all constants.
When compiling under VC++ I see the following warning:
warning C4244: '=' : conversion from 'int ' to 'unsigned char ', possible loss of data
I don’t understand this warning – none of the variables are of type int. Presumably some kind of implicit conversion is happening, but why?
Strangely, the following code (which is functionally identical) compiles with no warnings:
if (b == B1) {
a = A1;
} else {
a = A2;
}
So far as I’m aware, the two code extracts should be identical.
In C language arithmetic arguments of ternary
?:operator are subjected to usual arithmetic conversions, i.e. they are promoted tointbefore any further computations are performed. It doesn’t really matter whether they are constants or not. What matters is that they have typeunsigned char(as you said) andunsigned charunder?:is always promoted first. Basically, C language never performs any computations in types smaller thanint. Everything smaller is converted tointfirst.This is what happens in your case as well. Basically, your
is interpreted by C language as
and this is why you get the warning. Again, the fact that
A1andA2are constants plays no role whatsoever.The
does not subject the right-hand side to integral promotion, which is why there’s no warning here. Moreover, in this trivial case (direct assignment) even if
A1was explicitly declared as anintconstant, most compilers would not issue a warning if they could see that the constant is in range of the target typeunsigned char. The case with?:is more complicated, so the compilers might revert to the generic behavior and issue a warning.