Take the 2-minute tour ×
int main()
   int x,y;
   int z;
   char s='a';
   z = x/y;
   printf("%d\n",s); //97
   printf("%f",z); //some odd sequence
   return 0;


in the above piece of code the char s is automatically converted to int while printing due to the int type in control string, but in the second case the int to float conversion doesn't happen. Why so?

share|improve this question

4 Answers 4

up vote 7 down vote accepted

In both cases the second argument is promoted to int. This is how variadic functions work, and has nothing to do with the format string.

The format string is not even looked at by the compiler: it's just an argument to some function. Well, a really helpful compiler might know about printf() and might look at the format string, but only to warn you about mistakes you might have made. In fact, gcc does just that:

t.c:9: warning: format ‘%f’ expects type ‘double’, but argument 2 has type ‘int’

It is ultimately your responsibility to ensure that the variadic arguments match the format string. Since in the second printf() call they don't, the behaviour of the code is undefined.

share|improve this answer

Functions with variable number of arguments follow the rule of the default argument promotion. Integer promotion rules are applied on arguments of integer types and float arguments are converted to double.


sis a char and is converted to int.


z is already an int so no conversion is performed on z

Now the conversion specifier f expects a double but the type of the object after the default argument promotion is an int so it is undefined behavior.

Here is what C says on arguments of library functions with variable number of arguments

(C99, 7.4.1p1) "If an argument to a function has [...] a type (after promotion) not expected by a function with variable number of arguments, the behavior is undefined."

share|improve this answer

The char is not being promoted to int due to the control string. The char is working as an int because all data that is less than 4 bytes when passed to printf is bumped up to 4 bytes, which is the size of an int, because of the cdecl calling convention of variadic functions (the point of this is so that the data that comes next will be aligned on a 4-byte boundary on the stack).

printf is not type-safe and has no idea what data you really pass it; it blindly reads the control string and extracts a certain number of bytes from the stack based on what sequences it finds, and interprets that set of bytes as the datatype corresponding to the control sequence. It doesn't perform any conversions, and the reason you are getting some wierd printout is because the bits of an int are being interpreted as the bits of a float.

share|improve this answer
Can't it be that printf fetches arguments for the %f specifier from floating point registers? Unrelated: you typo'ed 'weird'. –  Daniel Fischer Jan 17 '12 at 15:25
@DanielFischer no, floating point values are also passed on the stack. You can see this by looking at the source code for the va_arg macro. –  Seth Carnegie Jan 17 '12 at 15:27

due to the int type in control string

That is incorrect. It is being converted because shorter int types are promoted to int by the var_args process. Int types are not converted to float types because the va/preprocessor doesn't know what formats are expected.

share|improve this answer

Your Answer


