4

Please have a look at this code:

#include <stdio.h>
int main(void)
{
short s = -1;

printf("sizeof(short) = %lu\n", sizeof(short));
printf("sizeof(int) = %lu\n", sizeof(int));
printf("sizeof(long) = %lu\n", sizeof(long));
printf("s = %hd\n", s);
printf("s = %d\n", s);
printf("s = %ld\n", s);

return 0;
}  

It gave output as :

sizeof(short) = 2  
sizeof(int) = 4  
sizeof(long) = 8  
s = -1  
s = -1  
s = 4294967295  

In last line why s = 4294967295 instead of s = -1 as through this question I came to know that In C when variable gets promoted, its value remains constant.

Community
  • 1
  • 1
rootkea
  • 1,474
  • 2
  • 12
  • 32

2 Answers2

6

s is being promoted to an int, which here is a 4 byte type. This is happening in all 3 cases. In the first two, an int is what printf() will expect, as the format specifier is for a type which would be passed as an int. However in the last case, you have given a format specifier which expects an 8-byte type.

This is invoking undefined behaviour.

In your case it appears to have read zeros in the upper bytes of the value, effectively zero-extending to 64-bits the value which was already sign-extended to 32-bits. However you can't depend on the results of doing this - it might be reading memory or a register that is not consistently initialised. Tomorrow it could be different.

The promotion of arguments is not dependent on the format string - you must always ensure that you pass the correct arguments for the format you have specified. So an int will not be promoted to a long. You need to convert it yourself.

A smart compiler ought to give you a warning about this.

JasonD
  • 16,464
  • 2
  • 29
  • 44
  • In second case `s` simply gets promoted to `int` then why not in last case ? Well, in case 2 I have given a format specifier which expects an 4-byte type but then the problem is solved by promptly promoting `s` to `int`. Same can be done in 3rd case. But it's not. Why? – rootkea Feb 07 '13 at 13:17
  • It *has* promoted it to an int. However the function tries to read a long, which is a different size. I have tried to add a clarification on what is probably happening to produce the result you see. – JasonD Feb 07 '13 at 13:21
  • Thanks! So do you mean whenever `printf` is called the argument is promoted to `int` type irrespective of the argument type ? And where does format specifier fit into this ? – rootkea Feb 07 '13 at 13:35
  • As I say in my answer, the format string does not influence the promotion. A short will always be promoted in the same way. If you think about it, the format string might be generated at run-time - in which case, the compiler could not know how to promote the arguments. So the rules are fixed in advance. – JasonD Feb 07 '13 at 13:49
1

The variable does not get promoted to long while calling printf("s = %ld\n", s);. The right way to promote it to long is printf("s = %ld\n", (long) s);.