-3

Possible Duplicate:
Why does printf print wrong values?

#include<stdio.h>

int main(int argc, const char *argv[]){
    float f1 = 125.2f;

    printf("\n [%f] [%d] [%g]",f1,f1,f1);
    printf("\n [%f] [%g] [%d]",f1,f1,f1);
    printf("\n [%g] [%f] [%d]",f1,f1,f1);
    printf("\n [%g] [%d] [%f]",f1,f1,f1);
    printf("\n [%d] [%g] [%f]",f1,f1,f1);
    printf("\n [%d] [%f] [%g]",f1,f1,f1);  
    getchar();
}  

I can see different output from each printf, though printing the same variable with same format identifier.

Community
  • 1
  • 1
Abhinav
  • 9
  • 5
  • 3
    How many times can this question get asked!? – Carl Norum Mar 21 '12 at 18:50
  • Those are format strings. You should read-up on `printf()`. – chrisaycock Mar 21 '12 at 18:51
  • First, this isn't C, as main() does not return void, but int. Second, the clrscr() method is not part of the C standard. Third, this is not objective-c you are dealing with, but pure C. Fourth, Please work on your code formatting before you post. – Richard J. Ross III Mar 21 '12 at 18:52
  • @CarlNorum It will be asked as many times as people come into programming without knowing anything - including how to do their own basic research (which also includes knowing that they can/should do their own research). This is a potentially very very large set of people. – Peter M Mar 21 '12 at 18:56

4 Answers4

3

printf is not type safe so using a incorrect format descriptor results in Undefined Behavior.

An Undefined Behavior means that any observable behavior is possible because the code is not abiding the rules laid out by the standard.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

Your code causes undefined behaviour. Anything can happen.

From the spec, section J.2 Undefined Behaviour:

There are insufficient arguments for the format in a call to one of the formatted input/output functions, or an argument does not have an appropriate type (7.19.6.1, 7.19.6.2, 7.24.2.1, 7.24.2.2).

So you could also check out the referenced sections for more information. In your case, the relevant bits are 7.9.16.1 The fprintf function, paragraph 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.

and 7.19.6.3 The printf function:

The printf function is equivalent to fprintf with the argument stdout interposed before the arguments to printf.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
0

The "%d" format requires an int argument. Passing a float argument (which promotes to double) results in undefined behavior.

What's probably happening is that printf is taking the wrong number of bytes from the stack, but your time is better spent fixing the code than figuring out why bad code misbehaves in a particular way.

And void main() is wrong; use int main(void). If some textbook told you that void main() is correct, the author doesn't know the language well enough to be writing about it.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
0

The details will vary based on the machine and compiler, but assume that a float is 4 bytes, a double is 8 bytes, and an int is 4 bytes.

You put three floats on the stack which are promoted to 8 bytes for a total of 24 bytes. Then your format string pulls various number of bytes off the stack. So

  • %f, %d, %g will pull 8, 4, 8 bytes
  • %f, %g, %d will pull 8, 8, 4 bytes
  • %g, %f, %d will pull 8, 8, 4 bytes
  • %g, %d, %f will pull 8, 4, 8 bytes
  • %d, %g, %f will pull 4, 8, 8 bytes
  • %d, %f, %g will pull 4, 8, 8 bytes

The type in vararg area of a printf must match the type expected by the conversion operator.

Lance Helsten
  • 9,457
  • 3
  • 16
  • 16
  • That's totally implementation dependent. Try it with a 64-bit app on a Mac, for example. – Carl Norum Mar 21 '12 at 20:26
  • Notice my first sentence: "details will vary based on the machine and compiler". Then I stated "assume" specific sizes for float, double, and int. – Lance Helsten Mar 22 '12 at 18:01
  • My point is that assuming sizes isn't enough. On a Mac (and maybe everything with AMD/Linux 64-bit ABI), floating point and integer variadic arguments are on independent logical stacks. Talking about pulling bytes off of a single stack is meaningless in that case. – Carl Norum Mar 22 '12 at 18:12
  • This was an example of what could go wrong, not an example of how to do it right. Therefore my final statement about matching types for vararg still stand. But your point about logical stacks is well taken. – Lance Helsten Mar 22 '12 at 18:18