1
#include <stdio.h>

int main(void)
{
  short i = 1;

  printf("%hd\n", i);
  printf("%hd\n", i * i);
  return 0;
}

Compiling this gives the warning warning: format specifies type 'short' but the argument has type 'int' [-Wformat] printf("%hd\n", i * i);.

Removing the printf("%hd\n", i * i); statement produces no warning.

Have I done something wrong? It is my understanding that since i has type short int that the value of the expression i * i has type short int but then printf performs an integer promotion to convert this short int result to int form before converting this int to short again (due to the conversion specifier).

I don't particularly see what is wrong about the code though. Is it just a warning telling me to be careful of the possibility that a more complicated expression than a simple short int variable being passed as an argument to printf corresponding to the %hd conversion specifier might result in overflow? Thanks!

user438383
  • 5,716
  • 8
  • 28
  • 43
The Skylur
  • 13
  • 1
  • 2
  • 5
    in `i * i` the arguments to the multiplication undergo ["integer promotions"](https://port70.net/~nsz/c/c11/n1570.html#6.3.1.1) and ["usual arithmetic conversions"](https://port70.net/~nsz/c/c11/n1570.html#6.3.1.8) and become `int` even before the multiplication is done. The final result of the multiplication is an `int`. – pmg Sep 24 '21 at 07:16
  • 1
    @pmg Please make this an answer. – the busybee Sep 24 '21 at 07:25
  • Ah right with the multiplicative operators the usual arithmetic conversions are applied on the operands and the usual arithmetic conversions itself specifies that the operands ```i``` in ```i * i``` undergo integer promotions making the value of ```i``` an ```int``` before the multiplication is performed. So essentially I am passing an ```int``` argument when it is expecting a ```short```. Performing the multiplication prior to the call of ```printf``` and assigning it to a ```short``` will remove the warning. But this particular warning isn't one I need worry about right? – The Skylur Sep 24 '21 at 07:29
  • The above program was just a snippet of a slightly larger but still very small program with the purpose of seeing at what number overflow occurs. – The Skylur Sep 24 '21 at 07:34
  • See [constants defined in ``](https://port70.net/~nsz/c/c11/n1570.html#5.2.4.2.1) ... `SHRT_MAX` et al :-) – pmg Sep 24 '21 at 07:38
  • Kind of a duplicate: [Implicit type promotion rules](https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules) – Lundin Sep 24 '21 at 08:59

1 Answers1

2

In i * i the arguments to the multiplication undergo "integer promotions" and "usual arithmetic conversions" and become int before the multiplication is done. The final result of the multiplication is an int.

The type of i * i is int (when type of i is int, short, char, or _Bool).


When you call printf with "%hd" the corresponding argument should be a short. What happens is that it is automatically converted to int and it's an int that printf sees. The internal code of printf will convert that int to a short to do its thing.
Problem is if you start with an int value outside the range of short.

short i = SHRT_MAX;
int j = i * i;
short k = i * i; // overflow while assigning
printf("%hd %hd", j, k);
//                ^ (kinda) overflow inside the innards of printf
pmg
  • 106,608
  • 13
  • 126
  • 198