[comp.std.c] A Little Quibble

mcdaniel@uicsrd.csrd.uiuc.edu (12/08/88)

Suppose I compile the following program under some dpANS C compiler:

    #include <stdio.h>
    main()
        {
	int a;
	a = 1;
	    {
	    int a = a;	/* X */
	    printf("a=%d\n", a);
	    }
	exit(0);
	}

Does dpANS require that "1" be printed, or is the result not defined
by dpANS?  In other words, in what environment is the right-hand-side
of line X evaluated?

Suppose I change line X to
	int b = a;    /* X' */
	int a = b;
Does the result change?  If the simplest translation
	int b, a;
	b = a; a = b;
is always done, the result is always undefined.

I ask this for two reasons:
- it's an interesting little quibble. :-)
- I would like to declare an invariant like this:
	double nubie;
	. . . compute nubie . . .
	{const double nubie = nubie;
	    . . . here, nubie is invariant . . .
	}

(I could also put "register" there to prevent passing "&nubie" to a
function to change it.  This use would only be for a compiler that is
smart enough to do its own register allocation, and ignore me totally.
:-)

By the way, here's another place where "typeof" would be convenient.
I could use
	#define FIX(x)	const typeof(x) x = x;
and code the example as
	{ FIX(nubie);
	. . . invariant nubie . . .
	}
Instead, I must use
	#define FIX(type, x)	const type x = x;
This is more error-prone, and it is harder to change the type of such
a FIXed variable.

--

             Tim, the Bizarre and Oddly-Dressed Enchanter

Center for      |||  Internet, BITNET:  mcdaniel@uicsrd.csrd.uiuc.edu
Supercomputing  |||  UUCP:     {uunet,convex,pur-ee}!uiucuxc!uicsrd!mcdaniel
Research and    |||  ARPANET:  mcdaniel%uicsrd@uxc.cso.uiuc.edu
Development,    |||  CSNET:    mcdaniel%uicsrd@uiuc.csnet
U of Illinois   |||  DECnet:   GARCON::"mcdaniel@uicsrd.csrd.uiuc.edu"

mcdaniel@uicsrd.csrd.uiuc.edu (12/09/88)

Please excuse more of my quibbling . . .

Is the program below legal under dpANS?   Is it guaranteed to output 1?

#include <stdio.h>
int a = 1;
main()
    {
    int a = 2; /* Y */
        {
        extern int a; /* Z */
        printf("%d\n", a);
        }
    }

On the VAX BSD 4.3 compiler, it complaints about line Z (redeclaration
of a).  If line Y is changed to "extern int a;", though, it compiles
fine.

What if I change line Z to "extern const int a;"?


About my base note's program (here reprinted)
    #include <stdio.h>
    main() {
	int a; a = 1;
	{ int a = a; printf("a=%d\n", a); }
	exit(0);
	}

The BSD 4.3 compiler apparently evaluates the right-hand side of
	int a = a;
in the context of the current block (as if it were
	int a; a = a;
); this program does not output "1".

--

             Tim, the Bizarre and Oddly-Dressed Enchanter

Center for      |||  Internet, BITNET:  mcdaniel@uicsrd.csrd.uiuc.edu
Supercomputing  |||  UUCP:     {uunet,convex,pur-ee}!uiucuxc!uicsrd!mcdaniel
Research and    |||  ARPANET:  mcdaniel%uicsrd@uxc.cso.uiuc.edu
Development,    |||  CSNET:    mcdaniel%uicsrd@uiuc.csnet
U of Illinois   |||  DECnet:   GARCON::"mcdaniel@uicsrd.csrd.uiuc.edu"

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/09/88)

In article <25200001@uicsrd.csrd.uiuc.edu> mcdaniel@uicsrd.csrd.uiuc.edu writes:
>Does dpANS require that "1" be printed, or is the result not defined
>by dpANS?

It's undefined (use of an uninitialized auto in an initializer expression).
Questions like this are resolved by the "scope rules".

>Does the result change?

Yes, now "a=1\n" must be printed.

>- it's an interesting little quibble. :-)

Not really.

>- I would like to declare an invariant like this:
>	double nubie;
>	. . . compute nubie . . .
>	{const double nubie = nubie;
>	    . . . here, nubie is invariant . . .
>	}

Multiple use of the same name for different purposes in the same
section of code is considered horrible style by every programmer
I know.

davidsen@steinmetz.ge.com (William E. Davidsen Jr) (12/10/88)

In article <25200001@uicsrd.csrd.uiuc.edu> mcdaniel@uicsrd.csrd.uiuc.edu writes:
| - I would like to declare an invariant like this:
| 	double nubie;
| 	. . . compute nubie . . .
| 	{const double nubie = nubie;
| 	    . . . here, nubie is invariant . . .
| 	}

How about:
  #define nubie ((const int) nubie)
or some such? I don't have the standard handy, but at worst I think you
would have to use another name, although I think there was something
about not recursively evaluating a macro...
-- 
	bill davidsen		(wedu@ge-crd.arpa)
  {uunet | philabs}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/10/88)

In article <25200002@uicsrd.csrd.uiuc.edu> mcdaniel@uicsrd.csrd.uiuc.edu writes:
>#include <stdio.h>
>int a = 1;
	EXTERNAL LINKAGE
	FILE SCOPE
	STATIC STORAGE DURATION
	TYPE int
	NAME "a"
	INITIALIZED TO THE VALUE 1 BEFORE PROGRAM EXECUTION STARTS
>main()
>    {
>    int a = 2; /* Y */
	NO LINKAGE
	BLOCK Y SCOPE (hides file-scope declaration of "a")
	AUTOMATIC STORAGE DURATION
	TYPE int
	NAME "a"
	RUN-TIME INITIALIZED TO THE VALUE 2 WHENEVER THIS POINT IS EXECUTED
>        {
>        extern int a; /* Z */
	EXTERNAL LINKAGE (since no visible file-scope declaration of "a")
	BLOCK Z SCOPE (hides both other declarations of "a")
	STATIC STORAGE DURATION
	TYPE int
	NAME "a"
	NO INITIALIZATION PERFORMED
>        printf("%d\n", a);
	This identifier "a" must be the block-Z declared one.
	Further, all external-linkage "a"s in all combined translation
	units and libraries must denote the same object.
	Therefore, "1" followed by a new-line must be printed.
>        }
	Block-Y-scope declared "a" is back in scope now.
>    }
	File-scope declared "a" is back in scope now.

>On the VAX BSD 4.3 compiler, it complaints about line Z (redeclaration of a).

That should be a lint-like usage warning, not a true diagnostic message.
The usage is legal C, but possibly a slip-up by the programmer.

>What if I change line Z to "extern const int a;"?

Qualified and unqualified versions of a type are distinct types belonging
to the same type category.  They do not have compatible types.  Therefore
the behavior is undefined.

>    #include <stdio.h>
>    main() {
>	int a; a = 1;
>	{ int a = a; printf("a=%d\n", a); }
>	exit(0);
>	}
>The BSD 4.3 compiler apparently evaluates the right-hand side of
>	int a = a;
>in the context of the current block (as if it were
>	int a; a = a;
>); this program does not output "1".

Yes, that's correct.  The identifier's scope starts right after its
declarator (i.e. before its initializer).  The initializer must use
the newly-introduced "a", not one that is not currently in scope.
Since the new object named "a" has not been given a value, random
junk may be printed (or other undefined behavior may occur).

All this stuff is covered in section 3.1.2 of the draft proposed
ANSI C standard.