In any C implementation, there are rules about how parameters are passed to functions. These rules may indicate that parameters of certain types are passed in certain registers (for example, integer types in general registers and floating-point types in separate floating-point registers), that large arguments (for example, structures with many elements) are passed onto the stack or a pointer to a copy of the structure, etc.
Inside the function being called, the function looks for the parameter that it expects in those places that are specified in the rules. When you pass an integer in the printf argument, but pass it %f in the format string, you put the integer somewhere, but tell printf to look for a float (which has been increased to double). If you specify in the C implementation rules that the integer argument is passed in the same place as the double argument, then printf will find the bits of your integer, but will interpret them as double. On the other hand, if the rules for your C implementation specify different places for the arguments, then the bits of your integers are not where printf looking for a double. So printf finds some other bits that have nothing to do with your integer.
In addition, many C implementations have 32-bit int types and 64-bit double types. The %f specifier is intended to print double, not float, and the float value you passed is converted to double before calling the function. Thus, even if printf finds the bits of your integer, there are only 32 bits, but printf uses 64. Thus, the printed double consists of 32 bits that you transmitted and 32 other bits, and this is not the value you plan to print .
This is why the format specifiers you use must match the arguments you pass.
source share