-2
int a=65; 
printf("%c", a);

I tried it on GCC on Ubuntu I don't know the version. But it worked and I wish to know how? Because according to me the size of char is smaller than int and hence it shouldn't have been possible.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    http://www.asciitable.com check for the 65 value on here. You'll find your answer. – Jose Rod Mar 05 '19 at 19:02
  • 2
    Please don't learn C by trial and error. There exists undefined behavior that may make you think something works one way based on some tests, but in reality is just illegal code that can break everything in the future. – Christian Gibbons Mar 05 '19 at 19:07

4 Answers4

1

The printf function has the following declaration:

int printf(const char *format, ...);

The first argument must be a pointer to a char array, but any additional arguments can be of any type, so it's not a compiler error if a format specifier mismatches the parameter (although it is undefined behavior).

This still works however because of what %c expects. From the man page:

If no l modifier is present, the int argument is converted to an unsigned char, and the resulting character is written. If an l modifier is present, the wint_t (wide character) argument is converted to a multibyte sequence by a call to the wcrtomb(3) function, with a conversion state starting in the initial state, and the resulting multibyte string is written.

From the above passage, %c actually expects an int and converts it to an unsigned char for printing. So if that's the case why does passing an actual char work? That is because of integer promotions. Any integer type smaller than int is promoted to int anyplace an int can be used. Since printf is variadic it can't check the types of its arguments, so a char passed to printf will get promoted to int when the function is called.

dbush
  • 205,898
  • 23
  • 218
  • 273
1

7.21.6.1 The fprintf function

...
8 The conversion specifiers and their meanings are:
...
c     If no l length modifier is present, the int argument is converted to an unsigned char, and the resulting character is written. If an l length modifier is present, the wint_t argument is converted as if by an ls conversion specification with no precision and an argument that points to the initial element of a two-element array of wchar_t, the first element containing the wint_t argument to the lc conversion specification and the second a null wide character.

C 2011 Online Draft

So, (f)printf expects the argument corresponding to the %c conversion specifier to have type int, and will convert it to unsigned char before formatting and displaying.

The value 65 can certainly fit in an unsigned char (0-255), so there's no problem with the conversion there. If you pass an integer value outside that range, then I suspect the following comes into play:

6.3 Conversions

6.3.1.3 Signed and unsigned integers
...
2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.60)
60) The rules describe arithmetic on the mathematical value, not the value of a given type of expression.

IOW, if you pass the value 321, it should "wrap" around back to 65 ('A' in ASCII).

John Bode
  • 119,563
  • 19
  • 122
  • 198
0

This is because of the default argument promotions. Anything smaller than int, when passed as part of printf's variable argument list, is converted to int before the call. Therefore, printf("%c", foo) cannot tell the difference between char foo and int foo. (However, if the value of the datum passed to %c is outside the range of unsigned char, the behavior is undefined.)

zwol
  • 135,547
  • 38
  • 252
  • 361
  • 1
    *the behavior is undefined* - I think it is defined, as `int` is converted to `unsigned char` according to http://port70.net/~nsz/c/c11/n1570.html#6.3.1.3p2 – Eugene Sh. Mar 05 '19 at 19:08
  • @EugeneSh. Hmm, you may be right. I said that because of [7.21.6.1p9](http://port70.net/~nsz/c/c11/n1570.html#7.21.6.1p9) "If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined" but the "correct type" for `%c` is in fact `int`. I remain not wholly certain that "converted to unsigned char" in the text of 7.21.6.1p8 means "as-if by the algorithm in 6.3.1.3p2", however. – zwol Mar 05 '19 at 19:14
0

It worked because it just print the the value of 65 converted to a char type in ASCII table 65 is the letter A so when you put:

int a = 65;
printf("%c", a); //---> a coverted to char type.

Check the ASCII table here ASCII table

raijin
  • 148
  • 1
  • 8