ccharformat-specifiersconversion-specifier

the reason why type char can be converted in specifier %d?


I suddenly noticed that i've used conversion specifier %d with type char although %d takes only type int.

How is it possible?

According to c standard, conversion specifier %d is corresponding to type int argument. And if any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

#include <stdio.h>
int main(void){
    char a= 'A'; // 'A' = 65 in ASCII

    printf("%c\n", a);
    printf("%d\n", a);

    return 0;
}

----- output -----
A
65

But whenever i compile the code like above , i always get output as intended.

Shouldn't i expect this output always?

Or, IS type char expanded to type int when passed to function's argument? So it can be 65 and i can use specifier %d with type char?


Solution

  • C 2018 6.5.2.2 7 says:

    … If the expression that denotes the called function [printf is that expression] has a type that does include a prototype [it does], the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters, taking the type of each parameter to be the unqualified version of its declared type. The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.

    printf is declared int printf(const char * restrict format, ...);, so, in printf("%d\n", a);, the "%d" argument corresponds to the format parameter, and the a corresponds to the ..., making it part of the trailing arguments. So the default argument promotions are performed on it. These are specified in 6.5.2.2 6:

    … the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions.

    The integer promotions are specified in 6.3.1.1 2:

    … If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions

    Thus your char argument a is automatically converted to an int, so it is the correct type for %d.