31

Are both these codes the same

char ch = 'a';
printf("%d", ch);

Will it print a garbage value?

I am confused about this

printf("%d", '\0'); 

Will this print 0 or garbage value? Because when i do this

printf("%d", sizeof('\n')); 

It prints 4. Why is sizeof('\n') 4 bytes? The same thing in C++ prints 1 bytes. Why is that?

So here's the main question

in c language is printf("%d", '\0') supposed to print 0

and in C++ printf("%d", '\0') supposed to print garbage?

Agustin Meriles
  • 4,866
  • 3
  • 29
  • 44

6 Answers6

54

%d prints an integer: it will print the ascii representation of your character. What you need is %c:

printf("%c", ch);

printf("%d", '\0'); prints the ascii representation of '\0', which is 0 (by escaping 0 you tell the compiler to use the ascii value 0.

printf("%d", sizeof('\n')); prints 4 because a character literal is an int, in C, and not a char.

peoro
  • 25,562
  • 20
  • 98
  • 150
  • @nightcracker: hm? If `printf("%d", ch);` "prints a garbage value", I guess it's because he wanted to print `A`, instead of its ascii value... – peoro Jan 19 '11 at 15:02
  • He never said anything printed a garbage value, he asked whether it will or not. – orlp Jan 19 '11 at 15:04
  • @nightcracker: hum, what's the difference? I'm not getting your point. – peoro Jan 19 '11 at 15:19
  • Simply put, your answer is not an answer to the OP's question. He was simply curious about the results of `%d` printing chars, `%c` is completely unrelated. – orlp Jan 19 '11 at 15:26
  • @nightcracker, I don't find it uncorrelated. OP was wondering if `printf("%d", 'a');` would print gargabe, couldn't that mean he was expecting `a` to be printed, instead of `96`? Other than explaining that `%d` prints ascii value, said that `%c` will print the character. I think this answer is similar to scoffey and John Bode isn't it? They don't say `%c` is used for chars, but that's just an extra point of this answer... – peoro Jan 19 '11 at 15:36
  • I saw your answer before you edited it, it only consisted of one line, "that the OP needed `%c`". Please don't try to fool me or other visitors by saying it's only a part of your answer. Either retreat your answer or stop defending it if it's faulty. – orlp Jan 19 '11 at 15:44
  • @nightcracker: it also contained "%d prints an integer: it will print the ascii representation of your character.". Later than that I expanded it by adding the example with `\0` and the comment about why `sizeof(int)` prints 4, but the semantics of my answer isn't changed (except for the addition of the comment about `sizeof`). – peoro Jan 19 '11 at 15:49
  • 10
    This is actually exactly what I was looking for (got here by search engine). Even if it doesn't answer OP's original question, it will help others – bobroxsox Feb 23 '17 at 21:54
9

This is supposed to print the ASCII value of the character, as %d is the escape sequence for an integer. So the value given as argument of printf is taken as integer when printed.

char ch = 'a';
printf("%d", ch);

Same holds for printf("%d", '\0');, where the NULL character is interpreted as the 0 integer.

Finally, sizeof('\n') is 4 because in C, this notation for characters stands for the corresponding ASCII integer. So '\n' is the same as 10 as an integer.

It all depends on the interpretation you give to the bytes.

scoffey
  • 4,638
  • 1
  • 23
  • 27
  • +1 so printf("%d", ch) will output (int) 97 and printf("%d", '\0') (int) 0 – BlackBear Jan 19 '11 at 15:12
  • I'd say that as "So '\n' is an int, 32 bits, 4 bytes, and sizeof() returns 4. The *value* of '\n' is 10, decimal. NEWLINE in ascii." The original, single sentence is true, but perhaps too terse. – Bill IV Apr 08 '11 at 23:20
7

In C char gets promoted to int in expressions. That pretty much explains every question, if you think about it.

Source: The C Programming Language by Brian W.Kernighan and Dennis M.Ritchie

A must read if you want to learn C.

Also see this stack overflow page, where people much more experienced then me can explain it much better then I ever can.

Community
  • 1
  • 1
orlp
  • 112,504
  • 36
  • 218
  • 315
  • @BlackBear: Yes, because (on most systems) a char is one byte and an int four, so it's a promotion. – orlp Jan 19 '11 at 15:02
  • I literally quote the book, they use the word promotion. It's the same as an int cast (I think). – orlp Jan 19 '11 at 15:06
  • I give you +1 for the link. The word promotion still confuses me though but I think you are clear ;). –  Jan 19 '11 at 15:09
  • The term "promotion" is also used in the C language standard, section 6.3.1.1. – John Bode Jan 19 '11 at 15:26
  • 1
    The promotion explanation is not very precise. `sizeof('a')` is 4 but `sizeof(ch)` is 1 if `ch` is a `char`. In C, the expression `'a'` is the same as `(int) 97`. There is no promotion. However, in C++, that expression has type `char`. – scoffey Jan 19 '11 at 15:38
7

In C, character constant expressions such as '\n' or 'a' have type int (thus sizeof '\n' == sizeof (int)), whereas in C++ they have type char.

The statement printf("%d", '\0'); should simply print 0; the type of the expression '\0' is int, and its value is 0.

The statement printf("%d", ch); should print the integer encoding for the value in ch (for ASCII, 'a' == 97).

John Bode
  • 119,563
  • 19
  • 122
  • 198
4
#include <stdio.h>
#include <stdlib.h>

int func(char a, char b, char c) /* demonstration that char on stack is promoted to int !!!
                                    note: this promotion is NOT integer promotion, but promotion during handling of the stack. don't confuse the two */
{
  const char *p = &a;
  printf("a=%d\n"
         "b=%d\n"
         "c=%d\n", *p, p[-(int)sizeof(int)], p[-(int)sizeof(int) * 2]); // don't do this. might probably work on x86 with gcc (but again: don't do this)
}


int main(void)
{
  func(1, 2, 3);

  //printf with %d treats its argument as int (argument must be int or smaller -> works because of conversion to int when on stack -- see demo above)
  printf("%d, %d, %d\n", (long long) 1, 2, 3); // don't do this! Argument must be int or smaller type (like char... which is converted to int when on the stack -- see above)



  // backslash followed by number is a oct VALUE
  printf("%d\n", '\377');             /* prints -1   -> IF char is signed char: char literal has all bits set and is thus value -1.
                                                     -> char literal is then integer promoted to int. (this promotion has nothing to do with the stack. don't confuse the two!!!) */
                                      /* prints 255  -> IF char is unsigned char: char literal has all bits set and is thus value 255.
                                                     -> char literal is then integer promoted to int */


  // backslash followed by x is a hex VALUE
  printf("%d\n", '\xff');             /* prints -1   -> IF char is signed char: char literal has all bits set and is thus value -1.
                                                     -> char literal is then integer promoted to int */
                                      /* prints 255  -> IF char is unsigned char: char literal has all bits set and is thus value 255.
                                                     -> char literal is then integer promoted to int */


  printf("%d\n", 255);                // prints 255


  printf("%d\n", (char)255);          // prints -1   -> 255 is cast to char where it is -1
  printf("%d\n", '\n');               // prints 10   -> Ascii newline has VALUE 10. The char 10 is integer promoted to int 10
  printf("%d\n", sizeof('\n'));       // prints 4    -> Ascii newline is char, but integer promoted to int. And sizeof(int) is 4 (on many architectures)
  printf("%d\n", sizeof((char)'\n')); // prints 1    -> Switch off integer promotion via cast!

  return 0;
}
spinooosa
  • 41
  • 2
  • 2
    Please limit your lines to 90 characters. One half of your text is hidden. – A.L Feb 28 '14 at 23:03
  • @A.L Blame those crazy 16:9 high resolution displays! With programmer friendly 4:3 aspect ratio, no one would ever write such crazy long lines ;) – BitTickler Feb 17 '21 at 00:00
-2

Yes, it prints GARBAGE unless you are lucky.

VERY IMPORTANT.

The type of the printf/sprintf/fprintf argument MUST match the associated format type char.

If the types don't match and it compiles, the results are very undefined.

Many newer compilers know about printf and issue warnings if the types do not match. If you get these warnings, FIX them.

If you want to convert types for arguments for variable functions, you must supply the cast (ie, explicit conversion) because the compiler can't figure out that a conversion needs to be performed (as it can with a function prototype with typed arguments).

printf("%d\n", (int) ch)

In this example, printf is being TOLD that there is an "int" on the stack. The cast makes sure that whatever thing sizeof returns (some sort of long integer, usually), printf will get an int.

printf("%d", (int) sizeof('\n'))
Jens
  • 69,818
  • 15
  • 125
  • 179
davep
  • 33
  • 1
  • 1
    -1 Almost everything is wrong here. Assuming the prototype for printf is visible, it is perfectly fine to pass a char or short to %d due to the integral promotions happening for variadic functions. Casting is silly at best. – Jens May 16 '12 at 21:35