Nasty bug

Barton E. Schaefer schaefer at ogicse.ogi.edu
Sat Sep 1 02:24:04 AEST 1990


In article <MEISSNER.90Aug31103238 at osf.osf.org> meissner at osf.org (Michael Meissner) writes:
} 
} In article <6441 at wolfen.cc.uow.oz> pejn at wolfen.cc.uow.oz (Paul Nulsen)
} writes:
} 
} | wallace at ynotme.enet.dec.com (Ray Wallace) writes:
} | 
} | >In article <0093BF08.7F3834E0 at rigel.efd.lth.se>, e89hse at 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 at cse.ogi.edu



More information about the Comp.lang.c mailing list