croes@imec.uucp (Kris Croes) (10/04/88)
Hello NetLand,
May I introduce to you...
A little program containing a big problem.
main()
{
int i = 17;
float f = 17.0;
printf("%d %f\n",i,i); /*1*/
printf("%d %f\n",f,f); /*2*/
}
Its output is:
17 0.000000
17032 0.000000
^^^^^^^^ Shouldn't this be 17.00000 ?
I am working under Ultrix 2.2, on a VAX-780 and had the same problem on
Apollo. BTW sizeof(int) = sizeof(float) = 4 on both machines.
Some tests (e.g. printing on several lines) showed that the problem is
caused by printing the float under the "%d" format. I know that
normal people don't do such a thing, but that is no reason for printf()
to mess up the stack. (???)
I know that not all binary numbers are valid floats. But if this was
the case, it would give problems in line /*1*/.
Why do things go wrong in line /*2*/ ? Is this a bug in my little
program, in printf(), in C , or where ?
K. Croes
--
--------
K. CROES - IMEC - Leuven - Belgium ..!prlb2!imec!croes
The Demon King sends a "rm -r /" to your shell.
tomp@nikhefk.UUCP (Tom Ploegmakers) (10/06/88)
In article <504@imec.UUCP> croes@imec.UUCP (Kris Croes) writes: > main() > { > int i = 17; > float f = 17.0; > > printf("%d %f\n",i,i); /*1*/ > printf("%d %f\n",f,f); /*2*/ > } > >Its output is: >17 0.000000 >17032 0.000000 > ^^^^^^^^ Shouldn't this be 17.00000 ? > This one has bitten me once too. The problem is that floats are not passed to functions on the stack, but by passing a pointer. That is, sometimes, you should check your compiler. To make it work use: printf("%d %f\n",i,(float)i); /*1*/ printf("%d %f\n",(int)f,f); /*2*/ Suc6. tom ploegmakers NIKHEF/K-CSG (tomp@nikhefk.uucp) po.box 4395, 1009 AJ Amsterdam, the Netherlands. -- tom ploegmakers NIKHEF/K-CSG (tomp@nikhefk.uucp) po.box 4395, 1009 AJ Amsterdam, the Netherlands.
dik@uva.UUCP (Casper H.S. Dik) (10/06/88)
In article <504@imec.UUCP> croes@imec.UUCP (Kris Croes) writes: >Hello NetLand, > >May I introduce to you... >A little program containing a big problem. > main() > { > int i = 17; > float f = 17.0; > > printf("%d %f\n",i,i); /*1*/ > printf("%d %f\n",f,f); /*2*/ > } > >Its output is: >17 0.000000 >17032 0.000000 > ^^^^^^^^ Shouldn't this be 17.00000 ? > No wonder, float arguments in C are converted to doubles before being passed to functions. So printf expects sizeof(int)+sizeof(double) bytes but gets sizeof(double)+sizeof(double). Since sizeof(double) > sizeof(float) this results in printf interpreting garbage as data, thus resulting in GIGO (Garbage In, Gospel Out). If you had read the entire printf manual, you would have been put on the right track by the explanation of %f '... converts the float or double argument ...'. BTW you posted to the wrong news group. Printf is a standard C function and the proper newsgroup would be comp.lang.c. ____________________________________________________________________________ Casper H.S. Dik Student University of Amsterdam | dik@uva.uucp The Netherlands | ...!uunet!mcvax!uva!dik ____________________________________________________________________________ Casper H.S. Dik University of Amsterdam | dik@uva.uucp The Netherlands | ...!uunet!mcvax!uva!dik
maart@cs.vu.nl (Maarten Litmaath) (10/07/88)
In article <504@imec.UUCP> croes@imec.UUCP (Kris Croes) writes:
\Hello NetLand,
\
\May I introduce to you...
\A little program containing a big problem.
\ main()
\ {
\ int i = 17;
\ float f = 17.0;
\
\ printf("%d %f\n",i,i); /*1*/
\ printf("%d %f\n",f,f); /*2*/
\ }
I have seen various explanations, none of them pointing out the ONLY error:
if you're telling printf() to expect an int (%d), SUPPLY it an int,
instead of a float!
--
Hippic sport: |Maarten Litmaath @ Free U Amsterdam:
a contradiction in terms.|maart@cs.vu.nl, mcvax!botter!maart
limes@ouroborous (Greg Limes) (10/08/88)
In article <504@imec.UUCP>, croes@imec (Kris Croes) writes: > int i = 17; > float f = 17.0; > > printf("%d %f\n",i,i); /*1*/ > printf("%d %f\n",f,f); /*2*/ >Its output is: >17 0.000000 >17032 0.000000 > ^^^^^^^^ Shouldn't this be 17.00000 ? Nope. You put a floating point number in the arg list, there is no guarantee that printf, expecting an integer, will do the right thing. Try: printf("%d %f\n", i, (float)i); printf("%d %f\n", (int)f, f); I expect that the float is being promoted to a double, which is taking up more space than an integer. Assuming 32 bit integers, 32 bit floats, and 64 bit doubles (not unreasonable), and arguments passed in memory, the %d would pick up the first 32 bits of the double precision 17.0 (==17032), and the %f would pick up the second 32 bits of the first double and the first 32 bits of the second double. In short, "printf" did not screw up your stack. "main" did, by passing badly typed parameters. -- Greg Limes [limes@sun.com] semper ubi, sub ubi
gwyn@smoke.ARPA (Doug Gwyn ) (10/08/88)
In article <504@imec.UUCP> croes@imec.UUCP (Kris Croes) writes: > printf("%d %f\n",i,i); /*1*/ >Some tests (e.g. printing on several lines) showed that the problem is >caused by printing the float under the "%d" format. I know that >normal people don't do such a thing, but that is no reason for printf() >to mess up the stack. (???) It wasn't printf that messed up the stack, it was you -- by not meeting the requirements for using printf. The arguments MUST match the corresponding conversion specifiers in the format string.
ark@alice.UUCP (Andrew Koenig) (10/08/88)
In article <504@imec.UUCP>, croes@imec.uucp (Kris Croes) writes: > Hello NetLand, > May I introduce to you... > A little program containing a big problem. > main() > { > int i = 17; > float f = 17.0; > printf("%d %f\n",i,i); /*1*/ > printf("%d %f\n",f,f); /*2*/ > } > Its output is: > 17 0.000000 > 17032 0.000000 > ^^^^^^^^ Shouldn't this be 17.00000 ? A float is automatically cast to double when used as an argument. Thus f probably takes up two words on the stack and %d picks off only one. Why do you want to use %d to print a float anyway? Incidentally, the %g format is usually more useful than %f. -- --Andrew Koenig ark@europa.att.com
ok@quintus.uucp (Richard A. O'Keefe) (10/10/88)
In article <429@nikhefk.UUCP> tomp@nikhefk.UUCP (Tom Ploegmakers) writes: >This one has bitten me once too. >The problem is that floats are not passed to functions on the stack, but by >passing a pointer. The problem is simply that when you pass a parameter to any function in pre-ANSI C, or to a function for which no prototype is in scope in dpANS C, (or in the "..." part of a call to a function which takes a variable number of arguments, such as printf()), the compiler is obliged to widen integral expressions to 'int' and floating-point expressions to 'double'. Thus when you do printf("...%d...%f...", f, f) f is widened to double: it is as if you did printf("...%d...%d...", (double)f, (double)f) Look up "argument conversions" in your favourite C textbook (page 135 in Harbison & Steele). If all else fails, it sometimes pays to look at the code your compiler generates. UNIX "C" compilers have a "-S" flag. Or you can use a debugger on the object file.
rosalia@mozart.UUCP (Mark Galassi) (10/11/88)
In article <504@imec.UUCP> croes@imec.UUCP (Kris Croes) writes: >A little program containing a big problem. > int i = 17; > float f = 17.0; > printf("%d %f\n",i,i); /*1*/ > printf("%d %f\n",f,f); /*2*/ > } Isn't it the case that the compiler promotes a float to a double (64bits on a VAX probably), thus making the stack different from what you thought it would be. I believe that that must be the case, because when you call sin(x) and x is just a float, it must be coerced to a double since the sin() func is written to take a double. -- Mark Galassi rosalia@mozart.UUCP These opinions are mine and should be everybody else's :-)
greyham@ausonics.OZ (Greyham Stoney) (10/13/88)
in article <504@imec.UUCP>, croes@imec.uucp (Kris Croes) says: > main() > { > int i = 17; > float f = 17.0; > > printf("%d %f\n",i,i); /*1*/ > printf("%d %f\n",f,f); /*2*/ ^^ ^ > } You have indeed broken the law. These sort of things just aren't defined; the ENTIRE output of BOTH printfs will be garbage (machine/compiler/system- dependant == garbage). float and ints probably (do usually) have different sizes, so a different ammount of info is passed for each one. When printf skips the space for the first 'f' in the arg list, it is actually skipping sizeof(int), cos that's what you told it was there; so it lands in the middle of the float when it looks for the second argument. > caused by printing the float under the "%d" format. I know that > normal people don't do such a thing, but that is no reason for printf() > to mess up the stack. (???) Yes it is.... you lied when you told it what the stack looked like. -- # Greyham Stoney: (disclaimer not necessary: I'm obviously irresponsible) # greyham@ausonics.oz - Ausonics Pty Ltd, Lane Cove. (* Official Sponsor *)