[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::decc

Title:DECC
Notice:General DEC C discussions
Moderator:TLE::D_SMITHNTE
Created:Fri Nov 13 1992
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:2212
Total number of notes:11045

2083.0. "dec c, alpha - /stan=vaxc -> error?" by CSC32::J_HENSON (Don't get even, get ahead!) Tue Feb 04 1997 13:21

Dec C for OpenVMS Alpha V5.5 (and V5.3), OpenVMS Alpha V6.2

A customer has provided sample code (below) that demonstrates differences
in results when compiled using /standard=vaxc or /standard=common
as opposed to not specifying a standard.

When this is compiled without specifying the standard, it produces
expected results (or at least what I would expect).  When compiled
with /standard=vaxc or /standard=common, it appears to treat the
two floats as d_floats in the pass_in_float routine, which results
in incorrect results from the printf statement.

Also, when compiled with /standard=common,  you get  ptrmismatch
warnings on one of the prototypes.

Using Dec C for OpenVMS Vax (v?), you still get the ptrmismatch warnings
when using /standard=common, but you get the same run-time results
regardless of the way it was compiled.

I'm not 100% sure that this is legal code, as it passes floats, by
value, from main to the 1st routine.  The 1st routine then passes
the same floats, by reference, to the 2nd routine.  In this particular
case it seems like it should be ok, but if the 2nd routine modified
the values, I would not expect the main routine to correctly see
the updates.  I don't know if this is relevant or not.

Please advise.

Jerry

=============================================================================

#include <stdio.h>

void intermediate_to_float();

main()
{
float x, y;

x = 20.5;
y = 30.2;

intermediate_to_float(x, y);
}

/*****************************************************************************/

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);
}

/*****************************************************************************/

void pass_in_float(float *x, float *y)
{
printf("x, y = %f %f\n", *x, *y);
}

T.RTitleUserPersonal
Name
DateLines
2083.1SPECXN::DERAMODan D&#039;EramoTue Feb 04 1997 14:3091
>#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.2The compiler has little choiceMOIRA::FAIMANWandrer, du M�der, du bist zu HausTue Feb 04 1997 15:3615
>        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 "&parameter" *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.3SPECXN::DERAMODan D&#039;EramoTue Feb 04 1997 18:2716
>.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 "&parameter" *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_HENSONDon&#039;t get even, get ahead!Wed Feb 05 1997 09:036
Great discussion, guys, but all I really want to know is whether or not
this is a bug, and why.

Thanks,

Jerry
2083.5wait, there's more...CSC32::J_HENSONDon&#039;t get even, get ahead!Wed Feb 05 1997 09:1721
>>       <<< 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.6Application bug, compounded by 'it used to work'VESPER::VESPEROpenGL Alpha GeekWed Feb 05 1997 10:0735
>        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.7Program is legal in ANSI C (only)WIBBIN::NOYCEPulling weeds, pickin&#039; stonesWed Feb 05 1997 10:3411
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.8OK, it is legal, but it still is wrongVESPER::VESPEROpenGL Alpha GeekWed Feb 05 1997 15:5611
>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