[comp.lang.c] float functions

gtchen@tybalt.caltech.edu (George T. Chen) (07/29/88)

Forgive me if I sound naive...

How do I get c to recognize a function as returning a float and not
a double?  It seems the moment I declare something as a function, the
compiler cast it as double.  I am primarily using sizeof to determine
the type.

Here is a sample code.

float f1()
{  return( (float) 10.0);
}

main()
{  float f1(), res;
   res = f1();
   printf("sizeof f1() is %d\n",sizeof(f1()));
   printf("sizeof res is %d\n",sizeof(res));
}

This program invariable returns 8 and 4, not 4 and 4.   Help.

		George


End of article 93282 (of 93283)--what next? [npq]
Message from sysop:  Your account has just been revoked for reading news!
Ha Ha.. just fooling. I'll let you back on now.

wlp@calmasd.GE.COM (Walter L. Peterson, Jr.) (08/02/88)

In article <7441@cit-vax.Caltech.Edu>, gtchen@tybalt.caltech.edu (George T. Chen) writes:
> 
> How do I get c to recognize a function as returning a float and not
> a double?  It seems the moment I declare something as a function, the
> compiler cast it as double.  I am primarily using sizeof to determine
> the type.
> 
> Here is a sample code.
> 
> float f1()
> {  return( (float) 10.0);
> }
> 
> main()
> {  float f1(), res;
>    res = f1();
>    printf("sizeof f1() is %d\n",sizeof(f1()));
>    printf("sizeof res is %d\n",sizeof(res));
> }
> 
> This program invariable returns 8 and 4, not 4 and 4.   Help.
> 

The results that you get, 8 and 4, while not correct are incorrect
for a different reason than the type of the function return value.

The local variable, res is 4 bytes, since you have declared it to be
float. In this case all is as it should be.  You are, however, expecting
that the sizeof value for f1() will also be 4 bytes; this is
incorrect.

In paragraph A7.4.8 Sizeof Operator (p204 in K&R 2ed.) it states:

   "The sizeof operator yields the number of bytes required to store
    an object of the type of its operand....The operator may not be
    applied to an operand of function type, or of incomplete type or
    to a bit-field."

Since the Second Edition of K&R follows the proposed ANSI standard and
your compiler may not, what I suspect is happening is that your
compiler's version of sizeof is returning the number of bytes in a
POINTER TO A FUNCTION, which could very well BE 8 bytes on your system.

In any case, a function is an inappropriate operand for the sizeof
operator and so you should not use it even if your compiler lets you
(if your compiler claims to be ANSI std. then I would say that this is
a bug in the compiler). 

So, don't worry. If you declare f1() as returning a float, it will
return a float.

-- 
Walt Peterson   GE-Calma San Diego R&D
"The opinions expressed here are my own and do not necessarily reflect those
GE, GE-Calma nor anyone else.
...{ucbvax|decvax}!sdcsvax!calmasd!wlp        wlp@calmasd.GE.COM

mesard@bbn.com (Wayne Mesard) (08/04/88)

From article <2890@calmasd.GE.COM>, by wlp@calmasd.GE.COM (Walter L. Peterson, Jr.):
> In article <7441@cit-vax.Caltech.Edu>, gtchen@tybalt.caltech.edu (George T. Chen) writes:
>> 
>> How do I get c to recognize a function as returning a float and not
>> a double?  It seems the moment I declare something as a function, the
>> compiler cast it as double.  I am primarily using sizeof to determine
>> the type.
> [stuff about sizeof deleted]
>
> So, don't worry. If you declare f1() as returning a float, it will
> return a float.

No no no!  All floating point arithmetic is done in double-preceision.
See K&R 6.2.  Floats are converted to doubles in expressions wherever
they appear (including return statments).

The following program should convince you that functions declared as
float and double always return double and if necessary are cast to float
in the calling routine.  (K&R doesn't address this specifically, but it
can be inferred from 6.2, from page 69 and by analogy to the char-int
conversion rules.)

==================SNIP=========================

float f()
{
    return(1.234567890123456789012345678901234567890);
}


double d()
{
    return(1.234567890123456789012345678901234567890);
}


main()
{
    float vff, vfd;
    double vdf, vdd;
    printf("%.32f\n%.32f\n", f(), d()); /* Same here */

    vff = vdf = f();
    vfd = vdd = d();
    printf("\n%.32f\n%.32f\n", vff, vdf); /* Different here */
    printf("\n%.32f\n%.32f\n", vfd, vdd); /* And here */
    
}

-- 
unsigned *Wayne_Mesard();        MESARD@BBN.COM           BBN, Cambridge, MA

pk-tle@nada.kth.se (Tommy Levitte) (08/04/88)

>> How do I get c to recognize a function as returning a float and not
>> a double?  It seems the moment I declare something as a function, the
>> compiler cast it as double.  I am primarily using sizeof to determine
>> the type.
>> 
>> Here is a sample code.
>> 
>> float f1()
>> {  return( (float) 10.0);
>> }
>> 
>> main()
>> {  float f1(), res;
>>    res = f1();
>>    printf("sizeof f1() is %d\n",sizeof(f1()));
>>    printf("sizeof res is %d\n",sizeof(res));
>> }
>> 
>> This program invariable returns 8 and 4, not 4 and 4.   Help.
>> 
> ...
>
>Since the Second Edition of K&R follows the proposed ANSI standard and
>your compiler may not, what I suspect is happening is that your
>compiler's version of sizeof is returning the number of bytes in a
>POINTER TO A FUNCTION, which could very well BE 8 bytes on your system.

WRONG!
to get the size of the pointer to the function f1(), you should use sizeof(f1).
Using sizeof(f1()) does return the size of the return value of f1().

Now there are a few rules which applies on parameter passing and value 
returnings.

  - A char is converted to an int.
  - A float is converted to a double.

This also applies in an expression of any kind.

So any float function will in fact return a double! And any float parameter
will in fact be a double!

Of course, at assignment time, it is converted back to float, if required.

Just to convince you and myself, I made this TurboC test:

float far f1(dummy1,x,y,dummy2)
float x;
double y;
int dummy1,dummy2;
{
   printf("In f1 :\n");
   printf("  &dummy1 = %lX\n",&dummy1);
   printf("  &x = %lX\n",&x);
   printf("  &y = %lX\n",&y);
   printf("  &dummy2 = %lX\n",&dummy2);
   printf("  sizeof(x) = %d\n",sizeof(x));
   printf("  sizeof(y) = %d\n",sizeof(y));
   printf("  sizeof(x+y) = %d\n",sizeof(x+y));
   printf("Exiting f1\n");
   return x+y;
}

main()
{
  float res;

  printf("sizeof(f1) = %d\n",sizeof(f1));
  printf("sizeof(f1()) = %d\n",sizeof(f1())); /* This is the size of the
                                                      return value */
  res=f1(0,3.0,4.0,0);
  printf("sizeof(res) = %d\n",sizeof(res));
  printf("sizeof(res+1.0) = %d\n",sizeof(res+1.0));
}

And I got the result is the following (I add some C-format comments):

sizeof(f1) = 4		/* The pointer to the function is 4 bytes */
sizeof(f1()) = 8	/* But this is the size of a double ! */
In f1 :
  &dummy1 = 19280FC2
  &x = 19280FC4	/* As you can see, x occupies the size of a double (8 bytes) */
  &y = 19280FCC	/* And so does y */
  &dummy2 = 19280FD4
  sizeof(x) = 4	/* At compile time, anyway, a float param is a float */
  sizeof(y) = 8
  sizeof(x+y) = 8	/* The expression is a double */
Exiting f1
sizeof(res) = 4		/* res is a float */
sizeof(res+1.0) = 8	/* but a float expression is allways double */
-- 
-------------------------------------------------------------------------------
Tommy Levitte (pk-tle@draken.nada.kth.se or gizmo@kicki.stacken.kth.se)
-------------------------------------------------------------------------------