0
#include <stdio.h>

int main()
{
  float i;
  i=1;
  printf("%d",i);
  return 0;
}

What should be the output of the code? Online compilers are giving garbage value but according to my logic shouldn't the float be converted to int and the float part get truncated and just print 1 as the output?

  • 1
    Undefined behavior is undefined. – DevSolar Dec 22 '22 at 09:36
  • If you want `i` to be converted to an int, you must change `printf("%d",i);` to `printf("%d", (int)i );`. The way you have written it, you are invoking undefined behavior, which means anything can happen, including garbage being printed. – Andreas Wenzel Dec 22 '22 at 09:38
  • By using `%d`, you are promising the function `printf` to pass a value of type `int`. By passing a value of type `float` instead, you are breaking this promise, thereby invoking undefined behavior. Most compilers will warn you when you do this. If your compiler did not warn you, then you probably should enable these warnings. See this question for further information: [Why should I always enable compiler warnings?](https://stackoverflow.com/q/57842756/12149471) – Andreas Wenzel Dec 22 '22 at 09:39
  • Asking to predict output of undefined behavior I consider a "not reproducable" question. Look up "undefined behavior". For fun, look up "nasal demons". – Yunnosch Dec 22 '22 at 09:41
  • If `printf` could independently check the argument types to perform conversions (without looking at the format string), it wouldn't require specifying the types in the string in the first place. E.g. since in C++ you can write functions with this limitation, libfmt (a modern replacement for `printf`) uses the same marker for most argument types. – HolyBlackCat Dec 22 '22 at 10:13

2 Answers2

2

No conversion is taking place in the way you assumed (*). The format specifier in the format string is used to determine what data type is expected next by va_arg. If the type specified in the format string does not match the type actually passed as parameter, behavior is undefined.


(*): With variadic arguments like printf there is a different type of conversion called "default argument promotion" happening, but that is a different subject altogether and is not being the issue you're facing.

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • A conversion _is_ taking place... the float value `i` is converted to a double. – Paul Hankin Dec 22 '22 at 09:45
  • Actually, there is a conversion to `double`. Read about "default argument promotions" in https://port70.net/~nsz/c/c11/n1570.html#6.5.2.2p6 – tstanisl Dec 22 '22 at 09:46
  • It is however correct to say that no conversion _to int_ is taking place. – Lundin Dec 22 '22 at 10:00
  • @tstanisl I am perfectly aware of those, but thought it irrelevant to the Q and actually distracting. I added a footnote. – DevSolar Dec 22 '22 at 10:10
2

It's made quite clear in the standard (e.g., C17 7.21.6.1 The fprintf function /9) that it is undefined behaviour of your argument types don't match the format specifiers:

9/ If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

So, in response to your question "What should be the output of the code?", the answer is "Whatever the implementation decides is best."

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Hmmm.... the point of leaving behavior undefined is that the implementation need not take that case into account, i.e. the implementation does not have to decide anything. (That would be "implementation-defined".) Just sayin'. – DevSolar Dec 22 '22 at 12:48
  • @DevSolar, I see that as still a decision, just one to not do anything explicit. These decisions are all made when creating an implementation, not when compiling. I suppose you could liken it to forgetting your anniversary because you chose not to write it down when you could. That's not a decision made on the day but much earlier. There's a subtle difference between actvely deciding to ignore the day and forgetting, which is really actively deciding earlier that it wasn't worth taking the effort to ensure you remembered. It's unlikely your partner will see the subtlety, however :-) – paxdiablo Dec 22 '22 at 20:28
  • The difference being that not covering for undefined behavior -- if it even were possible, which is it not from printf's view -- is not "lazyness" or "betrayal of trust", as your metaphor implies, but more along the lines of "I never **said** I could cure cancer, so don't expect me to..." – DevSolar Dec 22 '22 at 23:04