T.R | Title | User | Personal Name | Date | Lines |
---|
2083.1 | | SPECXN::DERAMO | Dan D'Eramo | Tue Feb 04 1997 14:30 | 91 |
| >#include <stdio.h>
>
>void intermediate_to_float();
No prototype for the arguments...
>main()
>{
>float x, y;
>
>x = 20.5;
>y = 30.2;
>
>intermediate_to_float(x, y);
>}
The two floats are "widened" to doubles; it is two doubles
that are passed to intermediate_to_float().
>/*****************************************************************************/
>
>void pass_in_float(float*, float*);
>
>void intermediate_to_float(x, y)
>float x;
>float y;
>{
>printf("x/y = %f %f\n", x, y);
>
> pass_in_float(&x, &y);
>}
intermediate_to_float() is declared "old style"; it takes two
doubles as arguments and then converts them to floats. As I
understand the language definition it should behave as if you
had written:
void intermediate_to_float(double arg1, double arg2)
{
float x = arg1;
float y = arg2;
{
/* original body of function goes here. */
printf("x/y = %f %f\n", x, y);
pass_in_float(&x, &y);
}
}
From the description of the problem, it sounds like the
compiler is using &arg1 and &arg2 instead of &x and &y in
pass_in_float(&x, &y);
both in terms of what is passed to pass_in_float() and in
terms of deciding that using "double *" where "float *" is
expected warrants a %CC-W-PTRMISMATCH warning. I.e., the
compiler seems to be behaving as if you had written:
void intermediate_to_float(double arg1, double arg2)
{
float x = arg1;
float y = arg2;
{
/* original body of function goes here. */
printf("x/y = %f %f\n", x, y); /* or x,y -> arg1,arg2 */
pass_in_float(&arg1, &arg2);
}
}
Whether the printf is using x,y or arg1,arg2 is harder to tell
but certainly the /standard=vaxc or /standard=common is making
the pass_in_float() call look like pass_in_float(&arg1, &arg2);
If so, then I'd say what the compiler is doing is wrong.
Why the VAX/Alpha difference?
On OpenVMS VAX the default for float/double is F_Float/D_Float.
On OpenVMS Alpha it is F_Float/G_Float. If you take a pointer
to an eight byte double and look at the first four bytes
pointed to and treat those four bytes as a float, then with
F_Float/D_Float the value represented by the float is the
almost the same as the value represented by the double--it
just has the least significant bits truncated. But with
F_Float/G_Float that is not the case, and the value
represented by the float is not similarly related to the value
represented by the double. So with the default floating point
type in use, you tend not to see a discrepancy on OpenVMS VAX
where it is difficult to miss it on OpenVMS Alpha.
Dan
|
2083.2 | The compiler has little choice | MOIRA::FAIMAN | Wandrer, du M�der, du bist zu Haus | Tue Feb 04 1997 15:36 | 15 |
| > Whether the printf is using x,y or arg1,arg2 is harder to tell
> but certainly the /standard=vaxc or /standard=common is making
> the pass_in_float() call look like pass_in_float(&arg1, &arg2);
>
> If so, then I'd say what the compiler is doing is wrong.
But, in traditional C programming, it was condoned to take the address of an
argument and then do pointer arithmetic to walk through the argument list. That
means that "¶meter" *has* to yield the address of the actual (promoted)
argument list entry, not the address of the local variable with the declared
type; otherwise, existing code would break. After all, the point of common mode
is to support old-fashioned C code as it was actually written, regardless of
whether it fit any standard.
-Neil
|
2083.3 | | SPECXN::DERAMO | Dan D'Eramo | Tue Feb 04 1997 18:27 | 16 |
| >.2
>But, in traditional C programming, it was condoned to take the address of an
>argument and then do pointer arithmetic to walk through the argument list. That
>means that "¶meter" *has* to yield the address of the actual (promoted)
>argument list entry, not the address of the local variable with the declared
>type; otherwise, existing code would break. After all, the point of common mode
>is to support old-fashioned C code as it was actually written, regardless of
>whether it fit any standard.
Well, yes, there is that. :-)
So the ansi modes do what you expect and the /standard=vaxc
and /standard=common modes do what you asked for; and what the
program asked for only works well for D_Float.
Dan
|
2083.4 | ? | CSC32::J_HENSON | Don't get even, get ahead! | Wed Feb 05 1997 09:03 | 6 |
| Great discussion, guys, but all I really want to know is whether or not
this is a bug, and why.
Thanks,
Jerry
|
2083.5 | wait, there's more... | CSC32::J_HENSON | Don't get even, get ahead! | Wed Feb 05 1997 09:17 | 21 |
| >> <<< Note 2083.4 by CSC32::J_HENSON "Don't get even, get ahead!" >>>
>> -< ? >-
>>Great discussion, guys, but all I really want to know is whether or not
>>this is a bug, and why.
And I may have just answered my own question.
When this is compiled on an alpha using either /stan=vaxc or /stan=common
AND /float=d_float, it appears to work correctly. When compiled on a
vax, using either /stan=vaxc or /stan=common AND /g_float, it appears
to fail. When compiled using Vax C with /g_float, it fails. So at
least the results are consistent among architectures and compilers when like
floating point formats are used.
I would still like confirmation, though. Some nifty verbage to explain
all of this would be appreciated, too.
Thanks,
Jerry
|
2083.6 | Application bug, compounded by 'it used to work' | VESPER::VESPER | OpenGL Alpha Geek | Wed Feb 05 1997 10:07 | 35 |
| > intermediate_to_float() is declared "old style"; it takes two
> doubles as arguments and then converts them to floats. As I
> understand the language definition it should behave as if you
> had written:
>
> void intermediate_to_float(double arg1, double arg2)
> {
> float x = arg1;
> float y = arg2;
> {
> /* original body of function goes here. */
> printf("x/y = %f %f\n", x, y);
> pass_in_float(&x, &y);
> }
> }
This is indeed the way that the ANSI/ISO standard says to treat such
a routine. However, VAXC, being pre-ANSI, treated it differently:
void intermediate_to_float(double x, double y)
{
printf("x/y = %f %f\n", x, y);
pass_in_float(&x, &y);
}
re .4
>Great discussion, guys, but all I really want to know is whether or not
>this is a bug, and why.
Yes, this is a bug in the application. The application is mixing float
and doubles and prototyped functions and non-prototyped functions. It only
worked because of certain characteristics of F-Float and D-Float.
Andy V
|
2083.7 | Program is legal in ANSI C (only) | WIBBIN::NOYCE | Pulling weeds, pickin' stones | Wed Feb 05 1997 10:34 | 11 |
| No, the program in .0 is just fine under ANSI C rules.
It's true that it mixes doubles and floats, and it's
true that it has some prototyped functions and some
without, but it doesn't mix them in any inconsistent
way. When you compile with /stand=ansi or /stand=relaxed,
the program gets the ANSI-defined behavior.
The program in .0 is not valid when interpreted under
the K&R-style rules, where &x means &arg1. Thus, when
you compile it with /stand=vaxc or /stand=common, you
get unexpected results.
|
2083.8 | OK, it is legal, but it still is wrong | VESPER::VESPER | OpenGL Alpha Geek | Wed Feb 05 1997 15:56 | 11 |
| >No, the program in .0 is just fine under ANSI C rules.
>It's true that it mixes doubles and floats, and it's
>true that it has some prototyped functions and some
>without, but it doesn't mix them in any inconsistent
>way. When you compile with /stand=ansi or /stand=relaxed,
>the program gets the ANSI-defined behavior.
Yes, you are right. However, I still claim the program
is wrong, bad, immoral and probably fattening as well.
Andy V
|