e89hse@rigel.efd.lth.se (08/30/90)
Hi ! I had a lot of trouble with a bug yesterday. The code was similar to the following: void main() { prnval("10.0",0.0); exit(0); } prnval(s,f) char *s; float f; { if(f == 0.0) sscanf(s,"%f",&f); printf("%10.2f\n",f); } And it didn't work. Why? The answer is that the parameter f is a double, not a float since all floats are converted to double when they are passed as arguments to functions. Therefore &f is a ptr to double rather than a ptr to float as one would expect looking at the declartion. Later I rewrote prnval() as: prnval(s,f) char *s; double f; { if(f == 0.0) sscanf(s,"%lf",&f); printf("%10.2f\n",f); } Well, I hope I'll help someone to avoid that problem... It took me a while to figure out why the code didn't work... Henrik Sandell Disclaimer: I know that this code wouldn't pass lint without warnings, but that is not the purpose of the code...
pierre@rhi.hi.is (Kjartan Pierre Emilsson) (08/30/90)
From article <0093BF08.7F3834E0@rigel.efd.lth.se>, by e89hse@rigel.efd.lth.se: > Hi ! > > I had a lot of trouble with a bug yesterday. The code was similar to the > following: > > [Code deleted] > prnval(s,f) > char *s; > float f; > > And it didn't work. Why? The answer is that the parameter f is a > double, not a float since all floats are converted to double when they are > passed as arguments to functions.Therefore &f is a ptr to double rather than > a float. > > Henrik Sandell I don't know what other think, but as a relatively experienced C programmer, I find this bug very counter-intuitive, being used to think that when I declare some variable in code to be of a given type, I certainly want it to be of that given type, regardless of what crap I choose to put in it later. From that point of view, float variables should not be allowed in function argument declaration. Personally I never use floats, but this is certainly a *very* nasty bug. -Kjartan ------------------------------------------------------------------------- Kjartan Pierre Emilsson Science Institute of the University of Iceland Dunhaga 3 Reykjavik ICELAND e-mail: pierre@krafla.rhi.hi.is
wallace@ynotme.enet.dec.com (Ray Wallace) (08/30/90)
In article <0093BF08.7F3834E0@rigel.efd.lth.se>, e89hse@rigel.efd.lth.se writes... > I had a lot of trouble with a bug yesterday. The code was similar to the >following: >And it didn't work. Why? The answer is that the parameter f is a >double, not a float since all floats are converted to double when they are >passed as arguments to functions. Therefore &f is a ptr to double rather than a >ptr to float as one would expect looking at the declartion. Sounds like a compiler bug to me. Floats are promoted to double in a procedure call but since your procedure declared the parameter as a float the compiler should have "demoted" the parameter so that &variable would work properly. FYI: Your code fragment worked properly with the VAX VMS-C compiler. --- Ray Wallace (INTERNET,UUCP) wallace@oldtmr.enet.dec.com (UUCP) ...!decwrl!oldtmr.enet!wallace (INTERNET) wallace%oldtmr.enet@decwrl.dec.com ---
walter@hpcllca.HP.COM (Walter Murray) (08/30/90)
Henrik Sandell writes: > I had a lot of trouble with a bug yesterday. The code was similar to the > following: [Program using an old-style (non-prototype) function definition with a parameter of type float] >And it didn't work. Why? The answer is that the parameter f is a >double, not a float since all floats are converted to double when they are >passed as arguments to functions. Therefore &f is a ptr to double rather than a >ptr to float as one would expect looking at the declartion. > Well, I hope I'll help someone to avoid that problem... It took me a while to >figure out why the code didn't work... You got bit by what is called type rewriting, something that was done by some pre-ANSI compilers. Although you declared the parameter as float, the compiler acted exactly as if you had declared it as double. Some compilers may also do this with parameters of type char or short, pretending that you had actually declared them as int. Type rewriting is not permitted for a compiler that conforms to the ANSI standard. A program that relies on type rewriting may not behave as expected when compiled with a standard-conforming compiler. For more information, see section 3.7.1 of the ANSI C Rationale. Walter Murray ------
volpe@underdog.crd.ge.com (Christopher R Volpe) (08/31/90)
In article <0093BF08.7F3834E0@rigel.efd.lth.se>, e89hse@rigel.efd.lth.se writes: |>void main() |>{ |> prnval("10.0",0.0); |> exit(0); |>} |> |>prnval(s,f) |>char *s; |>float f; |>{ |> if(f == 0.0) |> sscanf(s,"%f",&f); |> printf("%10.2f\n",f); |>} |> |>And it didn't work. Why? The answer is that the parameter f is a |>double, not a float since all floats are converted to double when they are |>passed as arguments to functions. It's true that f is promoted to double in the printf, but that's ok because printf expects a double when it sees %f. It knows that floats never get passed just as floats. Also, the scanf is ok here because you're passing a pointer to a float, and the %f tells scanf in this case that the argument is a pointer to a float, not a double. So, the printf and scanf are both ok here. I would expect that the problem is being caused not by printf or by scanf, but by the fact that the formal parameter to PRNVAL is declared as a float, when it is REALLY being passed a double from main(). (Anyone out there agree/disagree with this????) |>Therefore &f is a ptr to double rather than a |>ptr to float as one would expect looking at the declartion. No, &f is still a ptr to float, not a ptr to double. Floats get promoted, pointers don't. This isn't the problem. |>Later I rewrote |>prnval() as: |> |>prnval(s,f) |>char *s; |>double f; |>{ |> if(f == 0.0) |> sscanf(s,"%lf",&f); |> printf("%10.2f\n",f); |>} This is the correct solution anyway. |> |> Henrik Sandell ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
volpe@underdog.crd.ge.com (Christopher R Volpe) (08/31/90)
In article <2020@engage.enet.dec.com>, wallace@ynotme.enet.dec.com (Ray Wallace) writes: |> |>In article <0093BF08.7F3834E0@rigel.efd.lth.se>, e89hse@rigel.efd.lth.se |>writes... |>> I had a lot of trouble with a bug yesterday. The code was similar to the |>>following: |> |>>And it didn't work. Why? The answer is that the parameter f is a |>>double, not a float since all floats are converted to double when they are |>>passed as arguments to functions. Therefore &f is a ptr to double rather than a |>>ptr to float as one would expect looking at the declartion. |> |>Sounds like a compiler bug to me. Floats are promoted to double in a procedure |>call but since your procedure declared the parameter as a float the compiler |>should have "demoted" the parameter so that &variable would work properly. Doesn't sound like a compiler bug to me. The compiler should have "demoted" the parameter?!?!?! Huh?!?!?!? Is this some kind of crazy VAXism????? Where's it being demoted? By the caller? How would it know that it needs to demote it without a new style prototype in scope? By the callee, then?? How does it know what's being passed? There's no such thing as demoting parameters. |> |>FYI: Your code fragment worked properly with the VAX VMS-C compiler. Could be luck, based on compatible representations of float and double. But suppose on his machine, doubles have 2 more bits in the exponent? Passing a double to a function that expects a float will work about as well as passing an integer to a function that expects a float. |> |>--- |>Ray Wallace |> (INTERNET,UUCP) wallace@oldtmr.enet.dec.com |> (UUCP) ...!decwrl!oldtmr.enet!wallace |> (INTERNET) wallace%oldtmr.enet@decwrl.dec.com |>--- ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
browns@iccgcc.decnet.ab.com (Stan Brown, Oak Road Systems) (08/31/90)
In article <2117@krafla.rhi.hi.is>, pierre@rhi.hi.is (Kjartan Pierre Emilsson) writes: > From article <0093BF08.7F3834E0@rigel.efd.lth.se>, by e89hse@rigel.efd.lth.se: >> >> [Code deleted] >> prnval(s,f) >> char *s; >> float f; >> >> And it didn't work. Why? The answer is that the parameter f is a >> double, not a float since all floats are converted to double when they are >> passed as arguments to functions.Therefore &f is a ptr to double rather than >> a float. >> >> Henrik Sandell > > I don't know what other think, but as a relatively experienced C programmer, I > find this bug very counter-intuitive, [...] This isn't a bug--or at least it's not a compiler bug; it's the way the language is designed to work. Page 184, sec 6.2 of K&R 1: "whenever a float appears in an expression it is lengthened to double. ..." But I think the real moral of the story is, always use prototypes. The code shown above doesn't allow the compiler to do type checking. If the function were defined as int prnval(char *s, float f) { ... then the compiler is not just able but _required_ to type-check the arguments. (I think the original post had the function in the same source file and preceding the code of the function that called it. If that's not the case, then the prototype declaration would be need to be in scope.) Stan Brown, Oak Road Systems, Cleveland, Ohio, U.S.A. (216) 371-0043 The opinions expressed are mine. Mine alone! Nobody else is responsible for them or even endorses them--except my cat Dexter, and he signed the power of attorney only under my threat to cut off his Cat Chow!
volpe@underdog.crd.ge.com (Christopher R Volpe) (08/31/90)
In article <11477@crdgw1.crd.ge.com>, volpe@underdog.crd.ge.com
(Christopher R Volpe) forgets to do his homework:
Bart Schaefer corrected me on this one. I retract my last post.
I read the line sec A7.3.2 where it said "The effect of the call is undefined
if the ... type of an argument after promotion disagrees with that
of the corresponding parameter." (in K&R II). But I didn't realize
that they meant *promoted* type of the formal parameter. I should
have read the rest of the paragraph.
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com
pejn@wolfen.cc.uow.oz (Paul Nulsen) (08/31/90)
wallace@ynotme.enet.dec.com (Ray Wallace) writes: >In article <0093BF08.7F3834E0@rigel.efd.lth.se>, e89hse@rigel.efd.lth.se >writes... >>... Therefore &f is a ptr to double rather than a >>ptr to float as one would expect looking at the declartion. >Sounds like a compiler bug to me. I am not sure what the standard says, but this is definitely not a compiler bug. With old K&R style declarations the compiler does not know the type of a function argument until it sees the function definition. The function can be invoked before the definition is known, and hence before the argument types are known. In the case of floating point numbers, to avoid the problems this creates the approach adopted was to promote all floating point types to the common type of double. With ANSI style declarations this is no longer necessary. Compilers that accept ANSI style declarations have to accept the old style as well for backward compatibility, and if they are going to do this properly then they need to treat old style function definitions in the manner that they would have been treated, i.e. they have to promote all floats to doubles. This is what most compilers do. You will find that if you use ANSI style declarations the problem does not arise. I am surprised at the claim that VAX C does not promote the float to a double, for the reasons I have just outlined. Did you use the old style function definition in your test? As someone who does a lot of number crunching, I can tell you that the handling of floats in C is an significant obstacle to its use for heavy floating point computations. Argument promotion is one of a number of related gotcha's that make it difficult to write efficient single precision floating point code. If you just need a few numbers, doubles are fine, but when you are handling large data sets, the space and speed penalties can be serious. ANSI declarations solve the problem of automatic promotion, but there are of others. For example, the fact that floating constants are doubles combined with the rules for type promotion in expressions means that the following code float a, r; a = 3.1415926535 * r * r; results in the promotion of r (at least once) and then the demotion of the result back to float. To avoid this kind of trouble every constant has to be cast: a = (float) 3.1415926535 * r * r; which is a real pain. If you aren't pressed for time and space always use double's - you will probably end up using them whether you know it or not. If you are pressed for space or time and have to use float's, then pity you. Paul Nulsen pejn@wolfen.cc.uow.edu.au
asrap@warwick.ac.uk (Sean Legassick) (08/31/90)
In article <11473@crdgw1.crd.ge.com> volpe@underdog.crd.ge.com (Christopher R Volpe) writes: =In article <0093BF08.7F3834E0@rigel.efd.lth.se>, e89hse@rigel.efd.lth.se =writes: =|>Later I rewrote =|>prnval() as: =|> =|>prnval(s,f) =|>char *s; =|>double f; =|>{ =|> if(f == 0.0) =|> sscanf(s,"%lf",&f); =|> printf("%10.2f\n",f); =|>} = =This is the correct solution anyway. There is still a possible problem though. Comparing floating-point values to 0 like that can cause problems, especially if the values been put through the mangle of promotion etc. Its far less likely to cause problems if you use something like : if (f < 0.005) As the orginal poster did not describe the nature of the problem when the program was run (or compiled) this could have been the cause. =|> =|> Henrik Sandell = =================== =Chris Volpe =G.E. Corporate R&D =volpecr@crd.ge.com --------------------------------------------------------------------------- Sean Legassick, cuuee@uk.ac.warwick.cu "Improbability factor of one Computing Services asrap@uk.ac.warwick.cu to one. We have normality. University of Warwick Anything you still can't (the walking C obfuscator!) handle is your own problem."
scjones@thor.UUCP (Larry Jones) (08/31/90)
In article <0093BF08.7F3834E0@rigel.efd.lth.se>, e89hse@rigel.efd.lth.se writes: > > prnval(s,f) > char *s; > float f; > { > if(f == 0.0) > sscanf(s,"%f",&f); > printf("%10.2f\n",f); > } > > And it didn't work. Why? The answer is that the parameter f is a > double, not a float since all floats are converted to double when they are > passed as arguments to functions. Therefore &f is a ptr to double rather than a > ptr to float as one would expect looking at the declartion. It is worth noting that different C compilers handle this situation differently. Some do exactly what you said, they rewrite your parameter declaration as double rather than float. Others assign the passed double value to a local float which is then used as the parameter. If the float and double formats are sufficiently similar, the compiler can just ignore the second half of the passed double value and leave the parameter a float without having to make a copy. ANSI C does not allow the declaration rewriting -- it requires the compiler to make the parameter have the type you declared it as. So, this problem should not be a problem much longer, right? ---- Larry Jones UUCP: uunet!sdrc!thor!scjones SDRC scjones@thor.UUCP 2000 Eastman Dr. BIX: ltl Milford, OH 45150-2789 AT&T: (513) 576-2070 Hello, I'm wondering if you sell kegs of dynamite. -- Calvin
meissner@osf.org (Michael Meissner) (08/31/90)
In article <6441@wolfen.cc.uow.oz> pejn@wolfen.cc.uow.oz (Paul Nulsen) writes: | wallace@ynotme.enet.dec.com (Ray Wallace) writes: | | >In article <0093BF08.7F3834E0@rigel.efd.lth.se>, e89hse@rigel.efd.lth.se | >writes... | >>... Therefore &f is a ptr to double rather than a | >>ptr to float as one would expect looking at the declartion. | | >Sounds like a compiler bug to me. | | I am not sure what the standard says, but this is definitely not a compiler | bug. With old K&R style declarations the compiler does not know the type of | a function argument until it sees the function definition. The function can | be invoked before the definition is known, and hence before the argument | types are known. In the case of floating point numbers, to avoid the | problems this creates the approach adopted was to promote all floating point | types to the common type of double. With ANSI style declarations this is no | longer necessary. I would still argue it's a compiler bug, even in K&R-I. If you said float, what the compiler should do is realize that a double was passed, take said double, convert it to float, and store it somewhere (including back on the stack where it was passed). Then any references are still float, and not double. You do have a conversion from double to float in the procedure prologue. The same conversion goes for char and short parameters, though you can usually fake the address (and using the little endian false belief, you don't have to do that). The one good thing you could say about IBM floating point format, is that the float and double formats were the same, and you could ignore the bottom bits. ANSI requires the above behavior in the absence of prototypes. -- Michael Meissner email: meissner@osf.org phone: 617-621-8861 Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142 Do apple growers tell their kids money doesn't grow on bushes?
schaefer@ogicse.ogi.edu (Barton E. Schaefer) (08/31/90)
In article <MEISSNER.90Aug31103238@osf.osf.org> meissner@osf.org (Michael Meissner) writes: } } In article <6441@wolfen.cc.uow.oz> pejn@wolfen.cc.uow.oz (Paul Nulsen) } writes: } } | wallace@ynotme.enet.dec.com (Ray Wallace) writes: } | } | >In article <0093BF08.7F3834E0@rigel.efd.lth.se>, e89hse@rigel.efd.lth.se } | >writes... } | >>... Therefore &f is a ptr to double rather than a } | >>ptr to float as one would expect looking at the declartion. } | } | >Sounds like a compiler bug to me. } | } | I am not sure what the standard says, but this is definitely not a compiler } | bug. With old K&R style declarations the compiler does not know the type of } | a function argument until it sees the function definition. The function can } | be invoked before the definition is known, and hence before the argument } | types are known. In the case of floating point numbers, to avoid the } | problems this creates the approach adopted was to promote all floating point } | types to the common type of double. With ANSI style declarations this is no } | longer necessary. ANSI has nothing to do with it. Not knowing the type before invocation also has nothing to do with it. The only reason that floats are widened to double in a function call is because they are widened to double in all expression contexts. Similarly with char or short to int. } I would still argue it's a compiler bug, even in K&R-I. If you said } float, what the compiler should do is realize that a double was } passed, take said double, convert it to float, and store it somewhere } (including back on the stack where it was passed). Then any } references are still float, and not double. You do have a conversion } from double to float in the procedure prologue. To extend Michael's reasoning a bit: 1. The compiler (or more precisely, the compiler writer) knows that all floats will be promoted to double in expressions, including function calls. 2. It is legal to declare parameters to have type float. [%] 3. It is legal to take the address of a parameter. [%%] 4. From (2) and (3) it follows that taking the address of a parameter declared to be of type float must result in a pointer to type float. 5. From (4), it follows that the compiler must arrange that parameters declared to have type float will actually be represented as float (not double) when used in any function that takes the address of the float parameter. 6. From (2) and (1) it follows that the compiler (writer) knows that if the function was called with parameters of the correct types, any parameter declared float will have been promoted to double. Therefore all the information needed to handle (5) is available, and some implicit "demotion" must occur if the address of a float parameter is taken. How the compiler goes about dealing with (5) is not important -- it can treat float as synonymous to double as the standard practice, but it must special-case the unary & operator to be sure that it really does produce a pointer to a float, not a pointer to a double masquerading as a float. __________ % Someone questioned this legality on the basis of a passage in K&R1, page 42, which notes that throughout the text K&R used int and double for parameters, rather than char or float, because of promotions. There are no passages (unless you count the grammar) that explicitly permit parameters of type char/short/float. However, there also are no passages that explicitly forbid it, and it would have been trivial to prohibit it syntactically if that had been the intent. I therefore contend that page 42 is explaining a choice of programming style, not a language restriction. %% Of course you can't take the address of parameters declared register. Fortunately, that isn't at issue here. -- Bart Schaefer schaefer@cse.ogi.edu
chris@mimsy.umd.edu (Chris Torek) (09/02/90)
In article <7330028@hpcllca.HP.COM> walter@hpcllca.HP.COM (Walter Murray) writes: >You got bit by what is called type rewriting [in which a C compiler changes the type of a formal parameter declaration to match the type of any actual parameter passed by any caller, i.e., the compiler applies type-widening rules]. >Type rewriting is not permitted for a compiler that conforms to the >ANSI standard. ... ... except in the case of formal array parameters, where it is required: f(x) int x[]; { ... /* sizeof(x) == sizeof(int *) */ is the same as f(x) int *x; { ... /* sizeof(x) == sizeof(int *) */ and in fact the compiler is Officially Obliged to forget% that x was declared with empty square brackets rather than an asterisk. The situation is unchanged when prototype definitions are used. ----- % Well, modulo things not covered by the standard, such as program listings, error messages, and warnings. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
richard@iesd.auc.dk (Richard Flamsholt S0rensen) (09/03/90)
In article <11842@ogicse.ogi.edu> schaefer@ogicse.ogi.edu (Barton E. Schaefer) writes: >} | >In article <0093BF08.7F3834E0@rigel.efd.lth.se>, e89hse@rigel.efd.lth.se >} | >writes... >} | >>... Therefore &f is a ptr to double rather than a >} | >>ptr to float as one would expect looking at the declartion. >ANSI has nothing to do with it. Not knowing the type before invocation >also has nothing to do with it. The only reason that floats are widened >to double in a function call is because they are widened to double in >all expression contexts. Similarly with char or short to int. ^^^^^^^^^^^^^^^^^^^^^^^ Nope. ANSI states, that floats remain floats unless the expression contains more precise types, that is long double or double, in which case the float in converted. Therefore, if the float is the only parameter to a function it is *not* converted to a double in the expression, regardless of how the function was declared. Nothing has changed to the treatment of chars and shorts. These (and enums and bitfields) are still subject to integral promotion when found in an expression. Hmmm <thinking> - I might as well quote from app. A in K&R II, to make it totally clear: \begin{illegitimate quote ;-} First, if either operand is a long double, the other is converted to long double. Otherwise, if either operand is a double, the other is converted to double. Otherwise, if either operand is a float, the other is converted to float. Otherwise, the integral promotion is performed on both operands; [lotsa stuff about long/signed/unsigned/implementation dependencies deleted] \end{quote} As K&R sum it up: "The 'usual arithmetic conversions' has changed, essentially from 'for integers, unsigned always wins; for floating point, always use double' to 'promote to the smallest capacious-enough type'". CU. -- /Richard Flamsholt richard@iesd.auc.dk
scjones@thor.UUCP (Larry Jones) (09/04/90)
In article <RICHARD.90Sep3115406@orange.iesd.auc.dk>, richard@iesd.auc.dk (Richard Flamsholt S0rensen) writes: > Nope. ANSI states, that floats remain floats unless the expression > contains more precise types, that is long double or double, in which > case the float in converted. Therefore, if the float is the only > parameter to a function it is *not* converted to a double in the > expression, regardless of how the function was declared. No, you've confused the "Usual Arithmetic Conversions" with the "Default Argument Promotions". The Usual Arithmetic Conversions are the rules that you state -- float stays float. Note, however, that the compiler is usually allowed to get better results than you might expect, so the old promotion to double is still allowed. When calling a function which does not have a prototype in scope, however, the Default Argument Promotions are applied to each of the arguments. These rules state that the normal Integral Promotions are performed and that all floats are converted to double, just like always. ---- Larry Jones UUCP: uunet!sdrc!thor!scjones SDRC scjones@thor.UUCP 2000 Eastman Dr. BIX: ltl Milford, OH 45150-2789 AT&T: (513) 576-2070 When you're SERIOUS about having fun, it's not much fun at all! -- Calvin
steve@taumet.com (Stephen Clamage) (09/04/90)
richard@iesd.auc.dk (Richard Flamsholt S0rensen) writes: > Nope. ANSI states, that floats remain floats unless the expression >contains more precise types, that is long double or double, in which >case the float in converted. Therefore, if the float is the only >parameter to a function it is *not* converted to a double in the >expression, regardless of how the function was declared. This is just wrong. Section 3.2.1.5 describes the "usual arithmetic conversions", which are applied to binary operators. The standard allows a float to remain a float unless the other operand of the binary operator is double or long double. The last sentence of that section says: "The values of floating operands and of the results of floating expressions may be represented in greater precision and range than that required by the type; the types are not changed thereby." Thus ANSI allows floats to remain floats in expressions, but also allows them to be promoted to wider types. Furthermore, for function arguments, section 3.3.2.2 says: "If the expression that denotes the called function has a type that does not include a prototype, the integral promotions are performed on on each argument and arguments that have type float are promoted to double." It goes on to say: "If the expression that denotes the called function has a type that includes a prototype, the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters." So given the declarations: foo(float); doo(double); goo(); float f; We have the following calls: foo(f); /* f passed as a float * / doo(f); /* f widened to a double */ goo(f); /* f widened to a double */ -- Steve Clamage, TauMetric Corp, steve@taumet.com
chris@mimsy.umd.edu (Chris Torek) (09/04/90)
In article <RICHARD.90Sep3115406@orange.iesd.auc.dk> richard@iesd.auc.dk (Richard Flamsholt S0rensen) writes: > Nope. ANSI states, that floats remain floats unless the expression >contains more precise types, that is long double or double, in which >case the float in converted. This is *almost* right. The ANSI C standard does not say that a compiler cannot do `float f = 0.1; f += f;' as `convert f to double; add double to double; convert result to float', but it does give the compiler the option of doing it as `add float to float'. (This is similar to the fact that the standard does not require a compiler to, say, not insert delay loops after every few instructions ---except that the delay loops would be better proof of a stupid compiler! In other words, the standard does not, and cannot, outlaw bad code generation.) >Therefore, if the float is the only parameter to a function it is >*not* converted to a double in the expression, regardless of how the >function was declared. This, however, is almost completely wrong. When an actual parameter has type float, the value is not altered *only* when a function prototype is in scope and the corresponding formal parameter also has type float. If no prototype is in scope, or if the prototype has run into a `...', the value is widened. This is easily demonstrated by noting that float f; double d; ... (void) printf("%f %f\n", f, d); is correct: we do not need `%lf' to print d. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
richard@iesd.auc.dk (Richard Flamsholt S0rensen) (09/13/90)
In article <26350@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes: > In article <RICHARD.90Sep3115406@orange.iesd.auc.dk> richard@iesd.auc.dk > (Richard Flamsholt S0rensen) <that's me> writes: > > Nope. ANSI states, that floats remain floats unless the expression > >contains more precise types, that is long double or double, in which > >case the float in converted. > > This is *almost* right. The ANSI C standard does not say that a > compiler cannot do `float f = 0.1; f += f;' as `convert f to double; > add double to double; convert result to float', but it does give > the compiler the option of doing it as `add float to float'. Ooops - you're right: I'm wrong. Sure, optimizing is always legal. > >Therefore, if the float is the only parameter to a function it is > >*not* converted to a double in the expression, regardless of how the > >function was declared. > > This, however, is almost completely wrong. No, but I should have emphazied my point. The original poster claimed, that the float was converted, because it was part of an expression and, as he said, "-in expressions, floats are always converted to doubles". My objection to this was, that it isn't *the expression* which converts the float - it's the fact, that said expression is an argument to a function, which might convert it. Unfortunately, that point were lost in the function-business ... -- /Richard Flamsholt richard@iesd.auc.dk