Search code examples
ctypestype-conversionprintfstdio

Why char specified as integer in printf gets printed correctly


Why does the following code work?

char c = 'A';
printf("%d - size: %d", c, sizeof(c));

Prints out:

65 - size: 1

Why is the output not garbage, since an int would usually be 4 bytes long and we can clearly see that the char is 1 byte long. Does the compiler do the implicit conversation?


Solution

  • There is a special rule for functions with variable-length argument lists, like printf. In the variable-length portion of the argument list, all integral arguments smaller than int are promoted to int, and float is promoted to double. So it turns out it's perfectly fine to print a character (or a short) using %d.

    These default argument promotions end up accounting for a number of anomalies in printf. You might think that the correct format specifiers for char, short, int, float, and double are %hhd, %hd, %d, %f, and %lf, respectively. But in fact you can get away with %d, %d, %d, %f, and %f. printf basically ignores the l modifier for floating point, and it seems to ignore the h modifier for integers. (Actually h can make a difference in obscure cases, as chux explains in a comment.)