[comp.sys.sgi] Mixing ANSI and K & R 1 code.

karron@KARRON.MED.NYU.EDU (11/14/90)

I am working on modifying a software package written to run in the older
SGI compiler environment. I have just had LOTS of problems that I have finally
nailed down to mixing old and new argument styles.

Seems you can't have newstyle argument lists (ANSI) receiving parameters
from old styles,non prototyped code.

I first tried to write all my new stuff in ANSI code, but it would
always get float (Coord) arguments wrong. Finally, I had to recode my
new subroutines in old C style arguments.

ANSI C:void MyNewSubroutine(Coord x,Coord y,Coord z)
{ do da, do that thing }

K & R 1: void TheOldWayToAvoid(x,y,z)
Coord x,y,z;
{ do da, do that thing }


It seems a bit much to be forced to 1)rewrite ALL the old code in ANSI
style headers or
2) Write new stuff with old style headers.

This is something that should be fixed. There is a lot of code out there that
needs work, and I should not have to write new stuff in old style c.

dan.

+-----------------------------------------------------------------------------+
| karron@nyu.edu (mail alias that will always find me)                        |
|                                         Dan Karron                          |
| . . . . . . . . . . . . . .             New York University Medical Center  |
| 560 First Avenue           \ \    Pager <1> (212) 397 9330                  |
| New York, New York 10016    \**\        <2> 10896   <3> <your-number-here>  |
| (212) 340 5210               \**\__________________________________________ |
| Please Note : Soon to move to dan@karron.med.nyu.edu 128.122.135.3  (Nov 1 )|
+-----------------------------------------------------------------------------+

guy@auspex.auspex.com (Guy Harris) (11/17/90)

>Seems you can't have newstyle argument lists (ANSI) receiving parameters
>from old styles,non prototyped code.
>
>I first tried to write all my new stuff in ANSI code, but it would
>always get float (Coord) arguments wrong.

...

>This is something that should be fixed.

Fine, hop in your time machine, go back to the ANSI C meetings where
they decided that if you have a routine declared with prototypes with
arguments that are "float", that it really gets passed "float"s, not
"double"s, and convince them otherwise.  That should fix it....

If that's not possible, you're out of luck unless you can convince SGI
or whoever to have "float" just mean "double", which is unlikely given
the number of other things it'll probably break.... 

If you have a routine that is to have prototypes, is to be passed
floating-point arguments, and is to be called by old-style C, make its
arguments "double" - even if that means not giving them type "Coord".

karron@KARRON.MED.NYU.EDU (11/17/90)

>>Seems you can't have newstyle argument lists (ANSI) receiving parameters
>>from old styles,non prototyped code.
>>
>>I first tried to write all my new stuff in ANSI code, but it would
>>always get float (Coord) arguments wrong.
>
>...
>
>>This is something that should be fixed.
>
>Fine, hop in your time machine, go back to the ANSI C meetings where
>they decided that if you have a routine declared with prototypes with
>arguments that are "float", that it really gets passed "float"s, not
>"double"s, and convince them otherwise.  That should fix it....
>
>If that's not possible, you're out of luck unless you can convince SGI
>or whoever to have "float" just mean "double", which is unlikely given
>the number of other things it'll probably break....
>
>If you have a routine that is to have prototypes, is to be passed
>floating-point arguments, and is to be called by old-style C, make its
>arguments "double" - even if that means not giving them type "Coord".
>

Sgi has make a weak attempt to address this "standard" problem. There is a
 cc -float flag to stop default promotion to doubles in argument/parameter
lists. Just seems not to work they way I hoped in spliced code...

I am not finished testing this out, so if anyone has any more insight, I
would like for you to speak up.

My design goal is to mix a library of K & R 1 code with ANSI C, and when the
K & R stuff is upgraded, not change my ANSI C code. I guess that there
is no performance penalty for passing by value floats as doubles, but I am
not certain of it. It is more bytes to push to the stack. Another suggested
solution is to make ANSI headers for K & R 1 code. This is a slippery issue
and I am not certain  about a robust answer. At least the run time code really
breaks when the problem arises ! (Only with floats).

Cheers!

dan.

+-----------------------------------------------------------------------------+
| karron@nyu.edu (mail alias that will always find me)                        |
|                                         Dan Karron                          |
| . . . . . . . . . . . . . .             New York University Medical Center  |
| 560 First Avenue           \ \    Pager <1> (212) 397 9330                  |
| New York, New York 10016    \**\        <2> 10896   <3> <your-number-here>  |
| (212) 340 5210               \**\__________________________________________ |
| Please Note : Soon to move to dan@karron.med.nyu.edu 128.122.135.3  (Nov 1 )|
+-----------------------------------------------------------------------------+

goss@SNOW-WHITE.MERIT-TECH.COM (Mike Goss) (11/19/90)

> Date: Sat, 17 Nov 90 10:57:39 EST
> From: karron%karron.med.nyu.edu@cunyvm.cuny.edu
> Subject: Re: Mixing ANSI and K & R 1 code.
  ...
> 
> Sgi has make a weak attempt to address this "standard" problem. There is a
>  cc -float flag to stop default promotion to doubles in argument/parameter
> lists. Just seems not to work they way I hoped in spliced code...
> 
> I am not finished testing this out, so if anyone has any more insight, I
> would like for you to speak up.
  ...

The "-float" option on cc has never affected default promotion to
double in function arguments.  It only affects intermediate results in
floating point calculations. The cc man page in IRIX 3.3.1 explicitly says
this ("This option does not affect float function arguments, which are
always promoted to double unless function prototypes are used."), but
earlier versions (3.2) did not.

------------------------------
Mike Goss
Merit Technology Inc.
(214)733-7018
goss@snow-white.merit-tech.com

	Disclaimer: This offer void except where prohibited by law.

ciemo@bananapc.wpd.sgi.com (Dave Ciemiewicz) (11/19/90)

In article <9011171557.AA16135@karron.med.nyu.edu>, karron@KARRON.MED.NYU.EDU writes:
|> >>Seems you can't have newstyle argument lists (ANSI) receiving parameters
|> >>from old styles,non prototyped code.
|> >>
|> >>I first tried to write all my new stuff in ANSI code, but it would
|> >>always get float (Coord) arguments wrong.
|> >
|> >...
|> >

|> 
|> Sgi has make a weak attempt to address this "standard" problem. There is a
|>  cc -float flag to stop default promotion to doubles in argument/parameter
|> lists. Just seems not to work they way I hoped in spliced code...
|> 

Mr. Karron, you are mistaken.  From the cc(1) manual page:

     -float
          Cause the compiler to never promote expressions of type float to
          type double . This option does not affect float function arguments,
          which are always promoted to double unless function prototypes are
          used.

As is explained, -float has nothing to do with C function prototypes.  -float
is useful for preventing K&R style float-to-double conversion in floating
arithmetic operations.  The following example illustrates the problem.

	float a, b, c;

	c = a * b;

In K&R C, a and b, which are float are first both promoted to double, the
a double precision multiply occurs, the result is converted to float and
then assigned to c.

When doing numerical computations with lots of data, the expense of all the
floating point conversions between float and double may outweigh the benefit
of the extra precision.  This is especially true when doing dynamic 3D
graphics where a fast qualitative result may be a higher priority than
quantitative accuracy.

Invoking -float prevents the unneeded and expensive promotion to double in
the above example.

The ANSI C standard permits float arithmetic instead of requiring double.


|> I am not finished testing this out, so if anyone has any more insight, I
|> would like for you to speak up.
|> 
|> My design goal is to mix a library of K & R 1 code with ANSI C, and when the
|> K & R stuff is upgraded, not change my ANSI C code.
|>  Another suggested
|> solution is to make ANSI headers for K & R 1 code. This is a slippery issue
|> and I am not certain  about a robust answer. At least the run time code really
|> breaks when the problem arises ! (Only with floats).
|> 

Both you and the other gentlemen are probably falling into the following
trap.  This is not the result of a "weak attempt" on SGI's part to conform
to standards but a problem inherent in trying to mix K&R C with ANSI C.

If you have a library function coded as:

	float func(a, b)
	    float a;
	    float b;
	{
	    . . .
	}

you are using old style K&R C function declarations.  If you provide a
prototyped extern declaration, although it may be counter intuitive,
you should declare the prototype as:

	extern float func(double, double);

Why?  Well in the presence of K&R style coding of the function, the C
compiler must assume that you want K&R style float argument passing.  That
is, the call site must promote float arguments to double and then the called
function must convert the double arguments back to float.  This is most
assuredly the case when working with precompiled libraries built without
the use of function prototypes.  The above extern function prototype is
actually telling it like it is with K&R C style argument passing.


|> I guess that there is no performance penalty for passing by value floats
|> as doubles, but I am not certain of it. It is more bytes to push to the
|> stack.

Given the example above, do the call:

	float x, y, z;
	. . .
	
	z = func(x, y);

There is more than just the penalty of pushing twice as many bytes around
on the stack.  There also is the penalty of promoting x and y to double and
than back to float again inside func for a and b, as mentioned above.  These
conversions are extra cycles that are wasted.

By doing the ANSI C prototype conversion:

	extern float func(float, float);

	float func(float a, float b)
	{
	    . . .
	}

You are doing more than getting type checking, you telling the compiler to
be more efficient by eliminating 4 unnecessary type conversions, per function
call, 2 at the call site and 2 inside the function.

One last gotcha in this scenario is that once the function is implemented
with the prototype form, all call sites must agree on the calling conventions.
In this case, if you declare the function as:

	float func(float a, float b)
	{
	    . . .
	}

but call the function in an old K&R style module as:

	extern float func();

	float x, y, z;

	z = func(x, y); /* Fails because compiler promotes unknowingly
			   promotes x & y to double */

or without the benefit of an extern declaration, the call site will assume
K&R style function calls and thus fail.  The way to remedy this is to make
sure you have the ANSI C prototype extern declarations in header files for
all functions that you have changed to the ANSI C prototype convention.
These files must be appropriately included in each module which calls the
corresponding functions.

I hope this helps with the understanding of the issues involved in mixing
K&R C and ANSI C.

						--- Ciemo

davea@quasar.wpd.sgi.com (David B.Anderson) (11/20/90)

>Sgi has make a weak attempt to address this "standard" problem. There is a
> cc -float flag to stop default promotion to doubles in argument/parameter
>lists. Just seems not to work they way I hoped in spliced code...

The 3.3 cc man page tries to make it clear that -float does *not* apply to
arguments/parameters.  Check the -float option on the cc man page.

[ David B. Anderson  Silicon Graphics  (415)335-1548  davea@sgi.com ]
[``What can go wrong?''                           --Calvin to Hobbes]