[comp.lang.c] using floats in functional prototypes

romwa@gpu.utcs.toronto.edu (Royal Ontario Museum) (01/18/89)

I am reposting this query because I didn't receive any replies
to my original posting.  Can someone help out?

I am having some problems with using float's in functional
prototypes and am hoping that someone out there in netland can
help me out.  The problem seems to be isolated to float types
and not to any other types.  The examples below give the gist
of it.  Tst2.c has a function "afunc" with one parameter.
When I compile the two files, I get a warning that the type of
the argument in the prototype doesn't match the declaration
(??).  I experimented with this example a bit on a couple
of compilers and each time the warnings come out.  What is
more disconcerting is that flt_val inside afunc isn't 6.5 but
some bizarre value.
	A couple of other observations are that by changing
the type to be double made everything work, and by removing
the prototypes made everything work.  Since MS-C 5.1, QuickC,
and Turbo C give similar results I assume it is something
about C that I don't understand.

advTHANKSance

Totally Perplexed,

Pavneet Arora
...!utgpu!rom!pavneet

Royal Ontario Museum
100 Queen's Park
Toronto, Ontario
M5S 2C6
(416) 585-5626

---------tst.c-------------------------------------------------
#include <stdio.h>

void afunc( float );

void main( void )
{
  float flt_val = 6.5;

  afunc( flt_val );
}


---------tst2.c------------------------------------------------
#include <stdio.h>

void afunc( float );

void afunc( flt_val )

float flt_val;

{
  int i;

  i = 3;
}

Ralf.Brown@B.GP.CS.CMU.EDU (01/19/89)

In article <1989Jan18.092522.14499@gpu.utcs.toronto.edu>, romwa@gpu.utcs.toronto.edu (Royal Ontario Museum) writes:
}I am having some problems with using float's in functional
}prototypes ...
}When I compile the two files, I get a warning that the type of
}the argument in the prototype doesn't match the declaration
}---------tst2.c------------------------------------------------
}#include <stdio.h>
}
}void afunc( float );
}
}void afunc( flt_val )
}
}float flt_val;
}
}{
}  int i;
}
}  i = 3;
}}
}

The problem is that you are using an old-style declaration.  In old-style
declarations, parameters get widened according to specific rules.  One of
the rules is that floats get widened to double, so you are really declaring
a function that takes a double parameter.  That's why the compilers complain,
and also why you get garbage for the parameter--it is taking the four bytes
for the float plus an additional four bytes of garbage from the stack and
trying to interpret that as a double.

If you're going to use prototypes, you're pretty much going to have to use
new-style declarations when defining functions.
(i.e. void afunc(float flt_val) )

--
UUCP: {ucbvax,harvard}!cs.cmu.edu!ralf -=-=-=- Voice: (412) 268-3053 (school)
ARPA: ralf@cs.cmu.edu  BIT: ralf%cs.cmu.edu@CMUCCVMA  FIDO: Ralf Brown 1:129/31
			Disclaimer? I claimed something?
	You cannot achieve the impossible without attempting the absurd.

scjones@sdrc.UUCP (Larry Jones) (01/20/89)

In article <1989Jan18.092522.14499@gpu.utcs.toronto.edu>, romwa@gpu.utcs.toronto.edu (Royal Ontario Museum) writes:
> When I compile the two files, I get a warning that the type of
> the argument in the prototype doesn't match the declaration
> 
> void afunc( float );
> 
> void afunc( flt_val )
> float flt_val;
> {
>   int i;
> 
>   i = 3;
> }

The problem is that you have witten the function definition using
the old-style syntax.  When you do that, the function expects to
be called with widened arguments (i.e. the float argument will
actually be passed as a double).  To fix the problem, either
change the float in the prototype to double or write the
definition using prototype form:

	void afunc( float flt_val )
	{
	}

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc.UU.NET
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
"When all else fails, read the directions."

erc@pai.UUCP (Eric Johnson) (01/20/89)

[...]






In article <1989Jan18.092522.14499@gpu.utcs.toronto.edu>, romwa@gpu.utcs.toronto.edu (Royal Ontario Museum) writes:
> I am having some problems with using float's in functional
> prototypes and am hoping that someone out there in netland can
> help me out.  The problem seems to be isolated to float types
> and not to any other types.  The examples below give the gist
> of it.  Tst2.c has a function "afunc" with one parameter.
> When I compile the two files, I get a warning that the type of
> the argument in the prototype doesn't match the declaration
> (??).  I experimented with this example a bit on a couple
> of compilers and each time the warnings come out.  What is
> more disconcerting is that flt_val inside afunc isn't 6.5 but
> some bizarre value.
> 	A couple of other observations are that by changing
> the type to be double made everything work, and by removing
> the prototypes made everything work.  Since MS-C 5.1, QuickC,
> and Turbo C give similar results I assume it is something
> about C that I don't understand.
> advTHANKSance
> Totally Perplexed,
> 
> Pavneet Arora
> ...!utgpu!rom!pavneet
> 
> Royal Ontario Museum
> 100 Queen's Park
> Toronto, Ontario
> M5S 2C6
> (416) 585-5626




I, too, had problems using a float in a function prototype for MS C 5.1.
I recently upgraded from 4.0 to 5.1 and code that worked in 4.0, using
the float in a prototype, failed in 5.1.  If I remember correctly, the
5.1 compiler gave a warning message for the prototype.  The fix: I removed
the prototype and everything was hunky-dory.  The problem is that this
defeats the whole idea of using prototypes in the first place.  It is 
interesting that you state the problem appears in both Borland's and
Microsoft's compilers (we were thinking of switching to Turbo C, I 
guess we won't now).


If anyone has a code section using a float in a prototype that works
under MS C 5.1, I would appreciate the example code.  I may be doing
something wrong and I certainly wouldn't mind a constructive correction.

In my case, we used something like:
(I may have typed this in wrong, so no flames, please)


int foo( float /* f */, int /* i */, int /* j */ );


as the prototype


and


int
foo( f, i, j )

float	f;
int	i;
int	j;

{
/* ... */
}


as the function.  This seemed to cause great problems, as the float
value f never seemed to have the correct value upon entry to the
function.  This is no fun.  Again, removing the prototype seemed to
solve the problem. 


Does anyone have any ideas?  I would appreciate any, although dumping the
PC and getting a real computer is not really an option, no matter how
much I'd like to do that.


Thanks,
-Eric



[ Pavneet Arora's examples of the problem follow ]


> 
> ---------tst.c-------------------------------------------------
> #include <stdio.h>
> 
> void afunc( float );
> 
> void main( void )
> {
>   float flt_val = 6.5;
> 
>   afunc( flt_val );
> }
> 
> 
> ---------tst2.c------------------------------------------------
> #include <stdio.h>
> 
> void afunc( float );
> 
> void afunc( flt_val )
> 
> float flt_val;
> 
> {
>   int i;
> 
>   i = 3;
> }








-- 
Eric F. Johnson          | Phone +1 612-894-0313             | Are we
Prime Automation,Inc     | UUCP:   bungia!pai!erc            | having
12201 Wood Lake Drive    | UUCP:   sun!tundra!pai!erc        | fun
Burnsville, MN 55337 USA | DOMAIN: erc@pai.mn.org            | yet?

gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/21/89)

In article <365@pai.UUCP> erc@pai.UUCP (Eric Johnson) writes:
>Does anyone have any ideas?

Don't mix prototypes with old-style.  In particular, use a
prototype for the function definition also.

geoff@warwick.UUCP (Geoff Rimmer) (01/23/89)

In article <1989Jan18.092522.14499@gpu.utcs.toronto.edu> romwa@gpu.utcs.toronto.edu (Royal Ontario Museum) writes:

>---------tst.c-------------------------------------------------
>	#include <stdio.h>
>
>	void afunc( float );
>
>	void main( void )
>	{
>  		float flt_val = 6.5;
>
>  		afunc( flt_val );
>	}
>
>
>---------tst2.c------------------------------------------------
>	#include <stdio.h>
>
>	void afunc( float );
>
>	void afunc( flt_val )
>		float flt_val;
>
>	{
>  		int i;
>  		i = 3;
>	}

The problem is that you are using the old way of defining the function
afunc().  You should the new method:

	void afunc(float flt_val)
	{
	...
	}

BTW, rather than have to repeat the function prototype in both source
files, put it once in tst2.h, and get both tst.c and tst2.c to
#include "tst2.h".  Finally, if you want to do a function prototype
for a function with no arguments (e.g. main() in your example), the
PROTOTYPE should have 'void' between the parentheses, but the
DEFINITION shouldn't:

e.g., rewriting your tst.c

	#include <stdio.h>

	void afunc(float);
	void main(void); /* prototype  */
	void main()      /* definition */
	{
  		float flt_val = 6.5;

  		afunc( flt_val );
	}

	------------------------------------------------------------
	Geoff Rimmer, Computer Science, Warwick University, England.
			geoff@uk.ac.warwick.emerald

	"Why don't we go out for just ONE drink?"
	"No.  Because you know what would happen then, don't you?"
	"Lager Frenzie!"
	"And one thing you can't do after Lager Frenzie, is get up
	at 4.30 in the morning."
	"We could exercise restraint."
	"Yes, but then again in the real world, perhaps we couldn't!"

		- Filthy Rich and Catflap, 1986.
	------------------------------------------------------------

jbs@fenchurch.mit.edu (Jeff Siegal) (01/24/89)

In article <23d5d581@ralf> Ralf.Brown@B.GP.CS.CMU.EDU writes:
>If you're going to use prototypes, you're pretty much going to have to use
>new-style declarations when defining functions.

I don't see any reason that this is true.  You just need to know about
the promotion rules.

If you mix prototypes and old-style definitions, you can get code
which compiles on both old and new C compilers (assuming you use some
sort of conditional compilation to turn the prototypes into old-style
declarations).  You still get most of the advantages of prototypes.

Jeff Siegal

karl@haddock.ima.isc.com (Karl Heuer) (01/27/89)

In article <942@ubu.warwick.UUCP> geoff@emerald.UUCP (Geoff Rimmer) writes:
>...  Finally, if you want to do a function prototype for a function with no
>arguments (e.g. main() in your example), the PROTOTYPE should have 'void'
>between the parentheses, but the DEFINITION shouldn't:

I see no reason to make such an exception.  If you've got prototypes, use
them for both declarations and defintions, whether or not the function takes a
positive number of arguments.  In particular,
	int main(void) { return 0; }
is perfectly correct.  The old style (without `void') is obsolescent.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

geoff@warwick.UUCP (Geoff Rimmer) (02/01/89)

In article <11556@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes:
>In article <942@ubu.warwick.UUCP> geoff@emerald.UUCP (Geoff Rimmer) writes:
>>...  Finally, if you want to do a function prototype for a function with no
>>arguments (e.g. main() in your example), the PROTOTYPE should have 'void'
>>between the parentheses, but the DEFINITION shouldn't:
>
>I see no reason to make such an exception.  If you've got prototypes, use
>them for both declarations and defintions, whether or not the function takes a
>positive number of arguments.  In particular,
>	int main(void) { return 0; }
>is perfectly correct.  The old style (without `void') is obsolescent.

Well I don't know what the dpANS says about this, but I had problems
with QuickC not recognising that I had declared (prototyped) several
functions.  Eventually, I realised this behaviour was only happening
on functions with no params, then by changing for example 

	int main(void)  { ... }
to
	int main() { ... }

it worked fine.  Maybe its a bug in QuickC, but I've seen examples of
writing prototyped functions, and in every case the prototype takes
void, and the definition takes empty parentheses.

>Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

Geoff

	------------------------------------------------------------
	Geoff Rimmer, Computer Science, Warwick University, England.
			geoff@uk.ac.warwick.emerald

	"Came in? ... Isn't this where we"
		- Pink Floyd, The Wall
	------------------------------------------------------------

guy@auspex.UUCP (Guy Harris) (02/04/89)

 >>I see no reason to make such an exception.  If you've got prototypes, use
 >>them for both declarations and defintions, whether or not the function takes a
 >>positive number of arguments.  In particular,
 >>	int main(void) { return 0; }
 >>is perfectly correct.  The old style (without `void') is obsolescent.
 >
 >Well I don't know what the dpANS says about this,...

The dpANS most definitely says that

	int foo(void) { return 0; }

is perfectly correct.

It doesn't come right out and say that the old style (without `void') is
obsolescent; however, the May 13, 1988 draft says that an implementation
may generate a warning if "a function is called but no prototype has
been specified".  This sounds to me as if they don't think that
old-style definitions are the Right Way To Go; it sounds as if they
think they're kept around for backwards compatibility and should not be
used in new code. 

>Maybe its a bug in QuickC,

It most definitely *is* a bug in QuickC if it can't cope with

	int
	foo(void)
	{
		...
	}

and it purports to match some draft of the pANS.  If it doesn't purport
to match any draft of the pANS, it's simply a horrible misfeature.