mikel@ritcsh.cs.rit.edu (Mike Leibow) (12/11/90)
On some machines, the floats in the following program are promoted to doubles, and other machines, the floats remain floats. I believe that these floats shoud never look like doubles... What do you think? check(af1) float *af1; /* if this is "double," then this program works on most machines*/ { printf("%f\n", *af1); /* and you'd have to change %f to %lf */ } t(f1) float f1; { check(&f1); } main() { t(4.0); } If you post a followup, I'll probably not see it because our news disk is always full. Please send me email... --Mike mikel@ritcsh.cis.rit.edu
wirzeniu@cs.Helsinki.FI (Lars Wirzenius) (12/11/90)
In article <4268@ritcsh.cs.rit.edu> you write: >check(af1) >float *af1; /* if this is "double," then this program works on most machines*/ >{ > printf("%f\n", *af1); /* and you'd have to change %f to %lf */ >} Here, *af1 in the call to printf is a float that gets promoted to a double since it's used as a non-fixed argument to printf (i.e., as one of those arguments that can vary from one call to another). It is impossible to pass a float as a non-fixed argument. The same applies to old-style functions. These arguments go through "default argument promotion". This is described in K&R-2, Appendix A, Chapter 7.3.2, page 202, third paragraph (at least in my copy, your page number may wary). By the way, %f for printf means double, there isn't any conversion character for float (because of the reasons outlined above). >t(f1) >float f1; >{ > check(&f1); >} For old-style function definitions arguments of type float are silently rewritten to be of type double. So &f1 is actually a pointer to a double, which is inconsistent with check's expectation of a pointer to a float. You need a cast here to make everything work properly. It may be that your program is working only "by coincidence". Using new style function prototypes and definitions would probably take care of your problem. >main() >{ > t(4.0); >} 4.0 is a constant of type double. Since t actually does expect a double, everything should work OK as far as t is concerned.. >If you post a followup, I'll probably not see it because our news disk is >always full. Please send me email... Done. Lars Wirzenius wirzeniu@cs.helsinki.fi wirzenius@cc.helsinki.fi
tim@proton.amd.com (Tim Olson) (12/12/90)
In article <9919@hydra.Helsinki.FI> wirzeniu@cs.Helsinki.FI (Lars Wirzenius) writes: | In article <4268@ritcsh.cs.rit.edu> you write: | >t(f1) | >float f1; | >{ | > check(&f1); | >} | | For old-style function definitions arguments of type float are silently | rewritten to be of type double. Correct. | So &f1 is actually a pointer to a | double, which is inconsistent with check's expectation of a pointer to a | float. This isn't right -- type-rewriting does not take place for pointers; &f1 is still a pointer to a float. -- -- Tim Olson Advanced Micro Devices (tim@amd.com)
tim@proton.amd.com (Tim Olson) (12/12/90)
In article <1990Dec11.173043.8171@mozart.amd.com> tim@amd.com (I) write: | | >t(f1) | | >float f1; | | >{ | | > check(&f1); | | >} | | | | For old-style function definitions arguments of type float are silently | | rewritten to be of type double. | | Correct. | | | So &f1 is actually a pointer to a | | double, which is inconsistent with check's expectation of a pointer to a | | float. | | This isn't right -- type-rewriting does not take place for | pointers; &f1 is still a pointer to a float. After writing this, it was pointed out to me by wald@theory.lcs.mit.edu (David Wald) that I missed the fact that f1 was itself passed in as a parameter of type "float" with an old-style declaration -- I had mistakenly thought it was declared locally. To get back to the real question, then: K&R compilers tended to keep arguments of type "float" silently promoted to doubles, causing the problem that the original poster pointed out. ANSI-compliant compilers, however, must convert each incoming argument to the type of its corresponding parameter (as if by assignment). This solves the type-mismatch problem, and makes much more sense, as well! Note that this is not limited to floats/doubles; "narrowing" must occur for all types that have default widening rules, like char/short -> int. However, most K&R C compilers do the right thing with these. -- -- Tim Olson Advanced Micro Devices (tim@amd.com)