11

Why does the following call:

printf("%d %d", 'a', 'b');

result in the "correct" 97 98 values? %d indicates the function has to read 4 bytes of data, and printf shouldn't be able to tell the type of the received arguments (besides the format string), so why isn't the printed number |a||b||junk||junk|?

Thanks in advance.

azisso
  • 190
  • 1
  • 2
  • 11

3 Answers3

16

In this case, the parameters received by printf will be of type int.

First of all, anything you pass to printf (except the first parameter) undergoes "default promotions", which means (among other things) that char and short are both promoted to int before being passed. So, even if what you were passing really did have type char, by the time it got to printf it would have type int. In your case, you're using a character literal, which already has type int anyway.

The same is true with scanf, and other functions that take variadic parameters.

Second, even without default promotions, character literals in C already have type int anyway (§6.4.4.4/10):

An integer character constant has type int.

So, in this case the values start with type int, and aren't promoted--but even if you started with chars, something like:

char a = 'a';

printf("%d", a);

...what printf receives would be of type int, not type char anyway.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 1
    Default promotions? Really? Since when do varargs do default promotions? Isn't it just that the type of a character literal is `int`? – Oliver Charlesworth Oct 18 '10 at 13:42
  • 5
    Yes and no -- yes, a char literal has type `int`, but even if he assigned it to a `char` and passed that, `printf` would still receive an `int`, so it's pretty much irrelevant. – Jerry Coffin Oct 18 '10 at 13:45
  • 3
    No promotions are happening here. `'a'` and `'b'` have type `int` in C. – R.. GitHub STOP HELPING ICE Nov 14 '10 at 19:05
  • 1
    @R: Gee, thanks! I'm sure nobody else here noticed anything like that. *Closed captioning for the humor impaired*:If "@R" had bothered to read the previous comments, he'd see that everybody else noticed that weeks ago -- and that I already pointed out that/how it's irrelevant. – Jerry Coffin Nov 14 '10 at 19:26
  • 1
    @R.. Your point forced me to asked another question: Why is `printf("%d", (char)'a');` working fine? Does `printf` bypass coercion too? Do enlighten. :) – CᴴᴀZ Aug 14 '13 at 19:48
  • 1
    @ChaZ: Calls to variadic functions subject all the variadic arguments to *default promotions*, which promote all integer types with rank lower than `int` to `int` or `unsigned int` and promote `float` to `double`. It's fundamentally impossible to pass a `char` as a variadic argument. – R.. GitHub STOP HELPING ICE Aug 14 '13 at 19:54
  • @R.. So shall I presume that _promotions_ are happening here? – CᴴᴀZ Aug 14 '13 at 20:14
  • In the case of `printf("%d", (char)'a');`, the default promotions, which perhaps would be better described as *mandatory* promotions, result in the `char`-type expression `(char)'a'` being promoted to `int` before being passed to `printf`. In the case of `printf("%d", 'a');`, `'a'` simply has type `int` to begin with. – R.. GitHub STOP HELPING ICE Aug 14 '13 at 22:23
  • Here is a reference link (see section "Default conversions"): http://en.cppreference.com/w/cpp/language/variadic_arguments – felipou Apr 28 '14 at 19:56
4

In C, a char literal is a value of type int.

pmg
  • 106,608
  • 13
  • 126
  • 198
0

it prints the DEC ASCII for the characters entered by you.

Sunscreen
  • 3,452
  • 8
  • 34
  • 40