5

I have written a simple C program and wanted to know if integer promotion is happening in it.

Please explain how integer promotion happens and how to avoid it?

/* start of main */

unsigned short int res;
unsigned short int bsp;
signed short int analog;

bsp = 2215;
analog = 2213;
if((signed short int)(bsp - analog) > 0){
    res = bsp - analog;
    printf("%d", res);
}
else{
    res = analog - bsp;
    printf("%d", res);
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
Ravi
  • 69
  • 3
  • 1
    Hint: `printf("%d", res);`--> look there... – Sourav Ghosh Jul 07 '16 at 10:42
  • @Ravi for integer promotion see what Sourav said, however I have a doubt: instead of "integer promotion" did you mean "usual arithmetic conversion"? – Adriano Repetti Jul 07 '16 at 10:45
  • `bsp - analog` and `analog - bsp` both cause promotion. – Sergio Jul 07 '16 at 10:46
  • @AdrianoRepetti `... Otherwise, the integer promotions are performed on both operands. ...` (§6.3.1.8) – Sergio Jul 07 '16 at 10:56
  • @Adriano Repetti. You're splitting hairs unnecessarily. The conversion from `signed` to `unsigned` is described - by the C standards - as an integral promotion. – Peter Jul 07 '16 at 11:22
  • @Adriano. Read, for example, 1999 ISO C standard, Section 6.3.1.1. (end of para 2). "If an int can represent all values of the original type, the value is converted to an `int`; otherwise, it is converted to an `unsigned int`. These are called the integer promotions." – Peter Jul 07 '16 at 11:51
  • @Peter I see my previous comment sounds more rude than I expected, sorry for that. What I mean is: no, integer promotions imply no "conversion" and no possibly data loss. With a conversion you may (implementation defined) loose something. C standard (sorry I'm referring to C11, I can't check C99 now) they're described in separate places (and as separate things) because they happen in different places (with pretty different results). A promotion won't (probably) affect your code. A conversion may break it... – Adriano Repetti Jul 07 '16 at 11:56
  • Integer promotion occurs with 1) `bsp - analog` twice, 2) `(signed short int)(...) > 0)` 3) `printf("%d", res);` twice 4) `analog - bsp` – chux - Reinstate Monica Jul 07 '16 at 13:43
  • "how to avoid it" --> use `int/unsigned` rather than `unsigned short int/signed short int`. – chux - Reinstate Monica Jul 07 '16 at 13:47

2 Answers2

2

I'm going to restrict this answer to an int being 32 bit, and short being 16 bit.

Then bsp - analog is an expression of type int.

The behaviour on casting this to a short is undefined if bsp - analog cannot be represented in a short. So write code like (signed short int)(bsp - analog) with caution.

There's an implicit promotion of res to an int in your printf call.

Finally, the best way to avoid unwanted promotions is to work with the same type throughout. Consider using an int or a long in your case.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • NMDV, but `Finally, to circumvent the otherwise implicit promotion of res to an int in your printf call, use %hu as the formatter.` is probably not the correct words to be used. – Sourav Ghosh Jul 07 '16 at 10:52
  • notice , "the argument will have been promoted according to the integer promotions, but its value shall be converted to short int or unsigned short int before printing);" so, you never stop the promotion, actually. – Sourav Ghosh Jul 07 '16 at 10:53
  • 1
    @Bathsheba Isn't _"implementation defined"_ instead of _"undefined behavior"_? – Adriano Repetti Jul 07 '16 at 11:04
2

The integer promotions are issued from two different sources in your program:

  • usual arithmetic conversions (because of binary - operator1)
  • default argument promotions (because of printf variadic function)

In both cases, either argument of type signed short int is promoted to int, assuming, that int range can hold every number that former type can hold. Normally, it happens this way as short and int are 16-bit and 32-bit wide respectively.


1) As a well as of > operator (as mentioned in chux's comment below).

Community
  • 1
  • 1
Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137