I tested the following instruction which gives me a wrong result :
float tmp = 26.75 (data[8] (((SHORT) data[9]) << 8)) * 0.125 / 64;
Then, I tried to separate this instruction in two and it works :
SHORT ee = (data[8] (((SHORT) data[9]) << 8));
float tmp = 26.75 ee * 0.125 / 64;
I don't understand why this happens.
first_version:
float get_TMP () {
float tmp = 26.75 (data[8] (((SHORT) data[9]) << 8)) * (0.125) / 64;
return tmp;
}
last_version :
float get_TMP () {
SHORT ee = (data[8] (((SHORT) data[9]) << 8));
float tmp = 26.75 ee * (0.125) / 64;
return tmp;
}
and data is :
unsigned char data[10];
Here are the results :
(old) celsius is the result for the "last_version" (ok)
(new) celsius is the result for the "first_version" (error)
CodePudding user response:
In general, you should be very careful mixing signed integer types and unsigned integer types. In your example, you could also use signed char
. However, it is hard to say whether this is what you want.
Assume data[8] = data[9] = 0xFF
, char
is unsigned, SHORT
is signed short
, which is 16 bit, and signed int
is 32 bit. Then you compute (the u
after a constant means that the type is unsigned):
0xFFu (((signed short) 0xFFu) << 8)
=
0xFFu (0x00FF << 8)
= (integral promotion)
0xFFu (0x000000FF << 8)
=
0xFFu 0x0000FF00
= (integral promotion)
0x000000FFu 0x0000FF00u
=
0x0000FFFFu (an unsigned and positive number)
In the first example, you directly convert this number to float
and get a positive number.
In the second example, you convert this number to signed short
and obtain 0xFFFF and then back to signed int
and obtain 0xFFFFFFFF (a signed negative number). Then you convert it to float and obtain a negative number.