[vox-tech] totally confused about C promotion

Jeff Newmiller vox-tech@lists.lugod.org
Mon, 14 Jan 2002 15:56:50 -0800 (PST)


On Mon, 14 Jan 2002, Peter Jay Salzman wrote:

> 
> from kernighan and ritchie, page 45:
> 
>   For example, the library routine sqrt expects a double argument, and
>   will produce nonsense if inadvertantly handed something else.
> 
> consider the following code1.c:
> 
>    int main(void)
>    {
>    	long double var = 4.0L;
>    
>    	printf("%Lf\n", sqrt(var));
>    	return 0;
>    }
> 
> this prints nonsense (0.0000), since sqrt returns double and i'm
> printing a long double.  next, consider this code2.c:
> 
>    int main(void)
>    {
>    	long double var = 4.0L;
>    
>    	printf("%Lf\n", (long double)sqrt(var));
>    	return 0;
>    }
> 
> this works.  but i'm not really interested in just "working" because
> this particular code is extremely important to me.  i don't want to base
> my code on something that works by accident.

This problem has nothing to do with the argument to sqrt and everything to
do with the usage of printf and variable argument handling in C.  I assume
you forgot to show the #include <stdio.h>, but this encompasses a
prototype for sqrt so the function call is working fine.

> what happens when you hand a long double to a math function which
> expects a double?

Since you ask, it depends if a prototype is visible at the point of the
call.

If a prototype is not visible, it assumes you know what you are doing and
passes the value on the stack unchanged.  Note that a prototype is a
special form of function declaration _that includes types for the
arguments_.  Thus,

  double sqrt( arg )

is not a prototype, but 

  double sqrt( double arg )

is.

(It is also possible to forget to include the appropriate headers, so
the default declaration for any function call is

  int anyfunction(...)

which can bite you if you try to use sqrt without any declaration 
at all, such as including a suitable header.)

If a prototype is visible, it does a type-conversion to the type specified
for that argument, and passes the converted value, leaving the original
value unaffected.  You might or might not be happy with this conversion,
so do try to be aware of the types declared for the arguments you are
passing.

A good recipe for letting bugs creep into your code is to omit the gcc
options "-Wstrict-prototypes", "-Wmissing-prototypes", and
"-Wmissing-declarations".  It pays to be strict about not allowing your
code to produce warnings when these are used.

>  i can't find any rules for "demotion" in K+R.

I don't have K&R... any version.  Look up implicit type casting... should
be something under that.

> does code2.c work by accident or is there a concept of demoting floating
> points to a narrower width when the function expects them to be
> narrower?

Definitely the latter.

---------------------------------------------------------------------------
Jeff Newmiller                        The     .....       .....  Go Live...
DCN:<jdnewmil@dcn.davis.ca.us>        Basics: ##.#.       ##.#.  Live Go...
                                      Live:   OO#.. Dead: OO#..  Playing
Research Engineer (Solar/Batteries            O.O#.       #.O#.  with
/Software/Embedded Controllers)               .OO#.       .OO#.  rocks...2k
---------------------------------------------------------------------------