Go Down

Topic: Unexpected unsigned-to-signed promotion (Read 1 time) previous topic - next topic

dc42


I expected b to be promoted to a 16 bit type prior to the left shift, but I didn't expect the promotion to be from an unsigned type (byte) to a signed type (int).   It seems to me that it should have been promoted to an unsigned int.


From the C++ 2003 standard, section 4.5.1 on standard conversions:

"An rvalue of type char, signed char, unsigned char, short int, or unsigned short int can be converted to an rvalue of type int if int can represent all the values of the source type; otherwise, the source rvalue can be converted to an rvalue of type unsigned int. .... These conversions are called integral promotions."

and from section 5.8.1 on shift operations:

"The operands shall be of integral or enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand."

I agree, it's counter-intuitive.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Nick Gammon

This shows 0x8000:

Code: [Select]

  byte b = 0x80;
  unsigned long ul = 256;
  unsigned long r = b * ul;
  Serial.println(r, HEX);


So it appears that what dc42 said is correct (the second quote, about the shift operations).

Nick Gammon

Plus the next sentence in the standard (which I just downloaded) is very relevant:

Quote

The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.


So, undefined behaviour. :P

Nick Gammon

Or is it? Would both operands be promoted to unsigned long? But they can't be or the results would be 0x8000.

dc42


Or is it? Would both operands be promoted to unsigned long? But they can't be or the results would be 0x8000.


You need to distinguish between two types of conversion. Integral promotion is performed on a single operand. In the case of a shift operation, both operands are subject to integral promotion, independently of each other. The type of the right operand does not affect the type of the promoted left operand.

For binary arithmetic (not shift) operators, the "usual arithmetic conversions" are performed. In this case, the type of one operand can affect the type of the converted left operand. In particular, if one operand is unsigned int or a longer unsigned type, and the other operand has a signed type, then the other operand will be converted to unsigned. However, an expression of the form byte * byte will still be treated as int * int with the "unsigned" attributes discarded. See section 5.0.9 of the 2003 standard.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Go Up