[comp.windows.ms] FAR functions and float types

mms00786@uxa.cso.uiuc.edu (09/11/89)

Ok, I have wasted an entire weekend, so I hope wasting a little bandwidth is ok.

I am trying to write a medium model Windows program. I have certain functions
that are in seperate modules (obj files), and I need to call one from the other.
Here's what happens:

a) if I declare something like
   void FAR fnPlotSegment (hWnd, fFromX, fToX)
   HWND hWnd;
   float fFromX;
   float fToX;
   {...}
   then I am unable to pass the float type arguments! Everything compiles, runs,
   etc. but if I try to print the float values passed in, they are always 0.0!
b) if I declare something like
   void FAR PASCAL fnPlotSegment ...
   then windows crashes the first time I call it! As in, no warning, lets go 
   back to the C prompt and destroy the contents of the cmos setup too!
c) but the declaration
   void FAR fnPlotAnalog (hWnd, fFromX, fToX)
   HWND hWnd;
   double fFromX;
   double fToX;
   {....}
   works without a glitch! The only problem is that with this solution, I am
   unable to sleep, because the only way I can explain it is that I am getting
   lucky with the "double" declaration, and its going to crash on Tuesdays with
   a lunar eclipse when the Panda bear at the zoo get pneumonia.

Can someone please explain what I am doing wrong, or why any of the above makes
sense? I am using the medium model, but the small model has the same symptoms. I
am also compiling using the same line options that Petzold uses in his sample
make files. I am using MSC 5.0. I have scanned K&R and parts of the MSC manuals,
but the only difference between float and double should be the precision.

I am also having incredible problems trying to pass user defined types as
arguments to functions - as in just can't do it.

Please help before I flunk out of school.

Thanks,

Milan
mms00786@uxa.cso.uiuc.edu
.

bryant@flash.UUCP (Mike Bryant) (09/12/89)

In Microsoft C a formal parameter of type float  is  supposed  to
always  be  promoted to double (in the same way that char is pro-
moted to int). See the discussion in section 7.2.3, Formal Param-
eters,  of  the  Language Reference section of the manual. It ap-
pears that this must be broken based on the behavior you are see-
ing.  Section  5.6.4  states that actual parameters of type float
are always promoted to double (which must be working).

When using the pascal calling  convention  the  callee  pops  the
parameters  from  the  stack  (unlike C where the caller pops the
stack). If you call a function with the wrong number  of  parame-
ters  or the wrong types then the stack is corrupted. Most of the
time this causes a crash of some kind. In your case you are pass-
ing two doubles and the function expects two floats.

You discovered the solution to the bug on your own!
-- 
Mike Bryant      uunet.uu.net!amc!sigma!bryant
Summation Inc.   11335 NE 122nd Way  Kirkland, WA 98034

larry@csccat.UUCP (Larry Spence) (09/13/89)

In article <246400022@uxa.cso.uiuc.edu> mms00786@uxa.cso.uiuc.edu writes:
>Here's what happens:
>
>a) if I declare something like
>   void FAR fnPlotSegment (hWnd, fFromX, fToX)
>   HWND hWnd;
>   float fFromX;
>   float fToX;
>   {...}
>   then I am unable to pass the float type arguments! Everything compiles, runs,
>   etc. but if I try to print the float values passed in, they are always 0.0!

I believe that there is a documented bug in LINK4 (?) that screws up floats
passed to functions.  You'll have to either use pointers to floats, which you
may have to make static, or doubles.  The former is usually preferable.

>I am also having incredible problems trying to pass user defined types as
>arguments to functions - as in just can't do it.

I used to have a lot of problems with this.  For example, passing a param of 
type COMPLEX, where COMPLEX is a struct with the real and imaginary parts, 
caused all kinds of bizarre behavior.  The best thing to do is to pass a 
pointer instead, since the code generated is pretty simple in that case.  Note 
that the likelihood and severity of these problems varies slightly from 4.X to
5.X.

Larry Spence
larry@csccat
...{texbell,texsun,attctc}!csccat!larry

"Fatal Exit Code 0x0001!  Ack!"

kyler@pyr.gatech.EDU (J. Kyle Rogers) (09/13/89)

There was a note in one of the readme files included with
MSC 5.1 about how floating point arguments to functions
should all be double under ANSI C and, therefore, MSC 5.1
in order for everything to work correctly.  The note
explained the issue pretty well.  Sorry' I don't have access
to it at the moment, or I'd post it.

---krogers

|          krogers  --  J. Kyle Rogers  --  Technology Dynamics Inc.         |
|           145 15th Street N.E., Suite 624  --  Atlanta, GA 30361           |
|uucp: ...!{akgua,allegra,amd,hplabs,ihnp4,seismo,ut-ngp}!gatech!gitpyr!kyler|
|ARPA: kyler@pyr.gatech.edu                                                  |

mikek@ziebmef.mef.org (Mike King) (09/14/89)

In article <246400022@uxa.cso.uiuc.edu> mms00786@uxa.cso.uiuc.edu writes:
>Here's what happens:
>
>a) if I declare something like
>   void FAR fnPlotSegment (hWnd, fFromX, fToX)
>   HWND hWnd;
>   float fFromX;
>   float fToX;
>   {...}
>   then I am unable to pass the float type arguments! Everything compiles, runs,
>   etc. but if I try to print the float values passed in, they are always 0.0!
>c) but the declaration
>   void FAR fnPlotAnalog (hWnd, fFromX, fToX)
>   HWND hWnd;
>   double fFromX;
>   double fToX;
>   {....}
>   works without a glitch! The only problem is that with this solution, I am
>Milan

I've had the exact same problem with passing float arguments in Windows!
And I got around it by using doubles instead of floats.  I know people are
thinking "Changing to doubles pushes the stack around and maskes the real
bug", but I don't think so.  This application works flawlessly in debug	
Windows.  No problems anywhere else since I changed from floats to 
doubles?!?!?

It's very suspicious and I welcome any explanation.
	For reference: we compile using the alternate math library.

rogerson@PEDEV.Columbia.NCR.COM (Dale Rogerson) (09/16/89)

People have been having problems with functions to which tthey have passed
float types.  They solved this problem by uses doubles instead of floats.

Why does using doubles instead of floats work?  Because in ANSI C (which
MSC 5.1 is partly, somewhat, maybe, kinda, like ...) all float types are
promoted to doubles!!!  If you what to use floats and pass floats you must
use function prototypes.  Function prototypes stop the compiler from making
these type of automaic promotions.  

I found this out by reading the book:
	ANSI C: A Lexical Guide
	Published by Mark Williams Company
	Prentice Hall
	ISBN 0-13-037814-3

I just checked it out from the library today.  Learn something new everyday.
-----Dale
	Rogerson-----

mms00786@uxa.cso.uiuc.edu (09/17/89)

Thanks to all who responded, by email, here, and otherwise. The problem is that
the original K&R specified that all float arguments be promoted to double. To
avoid this promotion, you need to have funtion prototypes. Furthermore, the
prototypes have to be in the following format -

In files that will be using the extern function, you need something like this -

void far fnPlotSegment (int, float, float);

In the module that contains the function, you must have -

void FAR fnPlotSegment (int myVar1, float myVar2, float myVar3) 
{...
}

Note that the following will _not_ work -
void FAR fnPlotSegment (myVar1, myVar2, myVar3)
int myVar1;
float myVar2;
float myVar3;
{...
}

Once again thank you for clarifying this point. 

Milan
mms00786@uxa.cso.uiuc.edu
.

pdavid@polyslo.CalPoly.EDU (Paul C. David) (09/19/89)

mikek@ziebmef.mef.org (Mike King) writes:
>I've had the exact same problem with passing float arguments in Windows!
>And I got around it by using doubles instead of floats.  I know people are
	I was REALLY skeptical when I saw this the first
	time.  But I stand corrected, some co-workers
	recall seeing something about passing floats in
	the bug list on ONLINE.  Another good one is that
	you don't want to return doubles from a function,
	as this COULD foul up Global memory.  So.... you
	need to pass the double as a pointer, or declare
	your function as FAR PASCAL.  Have fun....
	-Paul.


-- 
Paul C. David		pdavid@polyslo.CalPoly.EDU
California Polytechic State University, San Luis Obispo
Home of the six-year or 60,000 mile undergraduate degree