3

What's going on here:

printf("result = %d\n", 1);
printf("result = %f\n", 1);

outputs:

result = 1
result = 0.000000

If I ensure the type of these variables before trying to print them, it works fine of course. Why is the second print statement not getting implicitly converted to 1.00000?

Dan
  • 33,953
  • 24
  • 61
  • 87

5 Answers5

8

In the second case you have a mismatch between your format string and the argument type - the result is therefore undefined behavio(u)r.

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • 9
    +1 for extra letter in "behaviour". Us Brits use it as backup in case anything nasty happens to the "o". – Moo-Juice Nov 16 '10 at 20:59
  • 1
    @Moo-Juice: Also so that the word has the full set of vowels available. – caf Nov 17 '10 at 01:58
  • 1
    @caf: Why can't I find the y? =) – Arkku Nov 17 '10 at 08:56
  • 1
    @Arkku: FYI, and completely off-topic, the word "facetiously" contains all the vowels (including y!) in alphabetical order - there is at least one other word in the English language which has the same property. – Paul R Nov 17 '10 at 10:36
4

The reason the 1 is not converted to 1.0 is that printf is “just” a C function with a variable number of arguments, and only the first (required) argument has a specified type (const char *). Therefore the compiler “cannot” know that it should be converting the “extra” argument—it gets passed before printf actually reads the format string and determines that it should get a floating point number.

Now, admittedly your format string is a compile-time constant and therefore the compiler could make a special case out of printf and warn you about incorrect arguments (and, as others have mentioned, some compilers do this, at least if you ask them to). But in the general case it cannot know the specific formats used by arbitrary vararg functions, and it's also possible to construct the format string in complex ways (e.g. at runtime).

To conclude, if you wish to pass a specific type as a “variable” argument, you need to cast it.

Arkku
  • 41,011
  • 10
  • 62
  • 84
  • Note that for variable arguments, `char` and `short` are promoted to `int` and `float` is promoted to `double`. – tomlogic Nov 16 '10 at 22:43
2

An undefined behavior. An int is being treated as float

BЈовић
  • 62,405
  • 41
  • 173
  • 273
1

The short answer is that printf isn't really C++. Printf is a C function which takes a variable argument list, and applies the provided arguments to the format string basis the types specified in the format string.

If you want any sort of actual type checking, you should use streams and strings - the actual C++ alternatives to good old C-style printf.

0

Interesting, presumably it's fine if your put '1.0'

I suppose the printf only gets the address of the variable, it has no way of knowing what it was. But I would have thought the compiler would have the decency to warn you.

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • The compiler doesn't know what types the function expecting. This is what makes variadic functions very ray to get wrong – Alexander Rafferty Nov 16 '10 at 21:01
  • @Alexander: note that some compilers, e.g. gcc, **do** check the format string for printf *et al* and can emit warnings for mismatches in the number and/or type(s) of the arguments. – Paul R Nov 16 '10 at 21:15