1
int_8 int8     = ~0;
uint_16 uInt16 = (uint_16) int8;

Regarding the typecast above; where in C standard can I find reference to an indication for the following behaviour? - sign extension to the larger type before the unsigned interpretation (uInt16=0xFFFF) rather than unsigned interpretation followed by 0 extension to the larger type (uInt16=0xFF).

From C99 6.3.1.8

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Above statement is clear about which variable needs to be converted however it is not very clear about how the conversation should actually be performed hence my question asking for a reference from the standard. Thanks

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
golark
  • 27
  • 7
  • Rule of thumb: `(uint_16)int8 + (uint_16)(-int8) == 0` should hold. – lorro Jul 29 '16 at 13:42
  • @lorro Disagree with `(uint_16)int8 + (uint_16)(-int8) == 0`. With `int_8,uint_16` as `int8_t, uint16_t`, on a 32-bit `int` machine, with `int8 > 0`, the result is always 65536 with a type of `int`. – chux - Reinstate Monica Jul 29 '16 at 14:46
  • @chux: yep, sorry, forgot the final cast. Fix: `(uint16_t)( (uint16_t)int8 + (uint16_t)(-int8)) == 0`. Thanks for spotting that! – lorro Jul 29 '16 at 15:15

2 Answers2

3

As per the standard:

6.3.1.3 Signed and unsigned integers

......
2. Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

And the footnote to avoid the confusion when interpreting the above:

The rules describe arithmetic on the mathematical value, not the value of a given type of expression.

I.e. if your int8 has a value of -1 (assuming the negatives representations is 2's complement, it does in your example), when converted into uint16_t, the value (0xFFFF + 1) will be added to it (which one more than the max value that can be represented by uint16_t), which yields the result of 0xFFFF + 1 - 1 = 0xFFFF.

Community
  • 1
  • 1
Eugene Sh.
  • 17,802
  • 8
  • 40
  • 61
  • thanks for your answer however I don't it is the answer I was looking for since unsigned conversion could happen before the zero/sign extension. i.e max value+1 could be added to int8 before zero extension giving 0xFF rather than max value+1 being added to int16 after the sign extension yielding 0xFFFF. – golark Jul 29 '16 at 14:49
  • If you look at the footnote in the link provided it says: *The rules describe arithmetic on the mathematical value, not the value of a given type of expression.*. So no notion of sign extension or whatever is relevant, as we are talking about pure arithmetics (added it to the answer). – Eugene Sh. Jul 29 '16 at 14:50
0

Answer I believe is actually part of 6.3.1.8 as well:

Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands: .... Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand.....

meaning that integer promotions are performed first before the conversion to unsigned using the rule 6.3.1.3.

golark
  • 27
  • 7