[net.lang.c] for != while

karl@haddock (09/01/86)

It's well known that the equivalence between for and while breaks down if
there's a "continue" statement.  Here's another case I just discovered:

main() {
	char *foo = "outer";
	for (;; printf(foo),exit(0)) {
		char *foo = "inner";
	}
}

This prints "outer" (vax SVR2 compiler), though the for-while equivalence
might lead one to expect "inner".

Karl W. Z. Heuer (ima!haddock!karl, karl@haddock.isc.com), The Walking Lint

ballou@brahms.BERKELEY.EDU (Kenneth R. Ballou) (09/02/86)

In article <86900030@haddock> karl@haddock writes:
>
>It's well known that the equivalence between for and while breaks down if
>there's a "continue" statement.  Here's another case I just discovered:
>
>main() {
>	char *foo = "outer";
>	for (;; printf(foo),exit(0)) {
>		char *foo = "inner";
>	}
>}
>
>This prints "outer" (vax SVR2 compiler), though the for-while equivalence
>might lead one to expect "inner".

I don't think the issue here is equivalence of for and while statements.
The point is that the scope of the inner 'foo' is the compound statement
which is the body of the for statement.  So, quite rightly, the 'foo'
given as the argument to printf in the third expression of the for statement
refers to the most closely nested declaration of 'foo' -- the body of the
for statement is one block level higher and is not visible at this point.

---------------

Kenneth R. Ballou                ...!ucbvax!brahms!ballou
Dept. of Mathematics
University of California
Berkeley, California  94720

mikeb@copper.UUCP (Mike Beckerman) (09/03/86)

In article <15525@ucbvax.BERKELEY.EDU> ballou@brahms.UUCP (Kenneth R. Ballou) writes:
>In article <86900030@haddock> karl@haddock writes:
>>
>>It's well known that the equivalence between for and while breaks down if
>>there's a "continue" statement.  Here's another case I just discovered:
>>
>>main() {
>>	char *foo = "outer";
>>	for (;; printf(foo),exit(0)) {
>>		char *foo = "inner";
>>	}
>>}
>>
>>This prints "outer" (vax SVR2 compiler), though the for-while equivalence
>>might lead one to expect "inner".
>
>I don't think the issue here is equivalence of for and while statements.
>The point is that the scope of the inner 'foo' is the compound statement
>which is the body of the for statement.  So, quite rightly, the 'foo'
>given as the argument to printf in the third expression of the for statement
>refers to the most closely nested declaration of 'foo' -- the body of the
>for statement is one block level higher and is not visible at this point.

That was my first thought as well, but both K&R and the proposed ANSI C standard
define the "for" loop as follows:

	for (expression-1 ; expression-2 ; expression-3) statement

		is equivalent to

	expression-1;
	while (expression-2) {
		statement
		expression-3;
	}

which to me says that the example should have printed "inner".

gt6294b@gitpyr.UUCP (SCHEUTZOW,MICHAEL J) (09/03/86)

> >It's well known that the equivalence between for and while breaks down if
> >there's a "continue" statement.  Here's another case I just discovered:
> >
> >main() {
> >	char *foo = "outer";
> >	for (;; printf(foo),exit(0)) {
> >		char *foo = "inner";
> >	}
> >}
> >
> >This prints "outer" (vax SVR2 compiler), though the for-while equivalence
> >might lead one to expect "inner".
> 
> The point is that the scope of the inner 'foo' is the compound statement
> which is the body of the for statement.  So, quite rightly...
> 
> Kenneth R. Ballou                ...!ucbvax!brahms!ballou

It took me a few minutes to figure out what Ken was saying, and he is 
quite right.  The above is equivalent to:

main()
{
char *foo = "outer";

    for (;;)
        {
            {
	    char *foo = "inner"; /* note the 'char' */
            }
        printf(foo);
        exit(0);
	}
}

Mike Scheutzow         "I _think_ these are my opinions;
Georgia Tech           let me ask my boss..."
gt6294b@gitpyr.uucp

operator@pogo.UUCP (Vax Operators) (09/04/86)

In article <570@copper.UUCP> mikeb@copper.UUCP (Mike Beckerman) writes:
>In article <15525@ucbvax.BERKELEY.EDU> ballou@brahms.UUCP (Kenneth R. Ballou) writes:
>>In article <86900030@haddock> karl@haddock writes:
>>>
>>>main() {
>>>	char *foo = "outer";
>>>	for (;; printf(foo),exit(0)) {
>>>		char *foo = "inner";
>>>	}
>>>}
>>>
>>>This prints "outer" (vax SVR2 compiler), though the for-while equivalence
>>>might lead one to expect "inner".
>>
>>I don't think the issue here is equivalence of for and while statements.
>>The point is that the scope of the inner 'foo' is the compound statement
                                                        ^^^^^^^^

>>which is the body of the for statement.  So, quite rightly, the 'foo'
>>given as the argument to printf in the third expression of the for statement
>>refers to the most closely nested declaration of 'foo' -- the body of the
>>for statement is one block level higher and is not visible at this point.
                       ^^^^^^^^^^^^^^^^^^
>
>That was my first thought as well, but both K&R and the proposed ANSI C standard
>define the "for" loop as follows:
>
>	for (expression-1 ; expression-2 ; expression-3) statement
>
>		is equivalent to
>
>	expression-1;
>	while (expression-2) {
>		statement
>		expression-3;
>	}
>
>which to me says that the example should have printed "inner".


I think the mistake being made here is a confusion with scope.  Yes,
that's the definition of while and for, but look carefully at the
definition for 'while':  it has { statement } (brackets surrounding
the statement) after the conditional, while the for has no brackets.
Therefore, the correct translation of your for loop into a while loop
is as follows:

main() {
	char *foo = "outer";
	while (TRUE)
	{
		{
			char *foo = "inner";
		}
		printf(foo);
		exit(0)
	}
}

The for loop execution order is  /* for (exp1; exp2; exp3) statement; */

		exp1;		<=>	    ;
		exp2;		<=>	    ;
		statement;	<=>	{ char *foo = "inner" }
		exp3;		<=>	printf(foo); exit(0);


The 'char *foo = "inner"' disappears when the deeper scope gets popped,
therefore the foo that gets printed is still "outer".

Shannon Nelson
"Where there is a will, there's lot's of relatives...'

brett@wjvax.UUCP (Brett Galloway) (09/04/86)

In article <86900030@haddock> version B 2.10.3 4.3bsd-beta 6/6/85; site wjvax.wjvax.UUCP wjvax!qubix!saber!sun!decwrl!pyramid!hplabs!qantel!lll-lcc!lll-crg!nike!think!ima!haddock!karl karl@haddock writes:
>
>It's well known that the equivalence between for and while breaks down if
>there's a "continue" statement.  Here's another case I just discovered:
>
>main() {
>	char *foo = "outer";
>	for (;; printf(foo),exit(0)) {
>		char *foo = "inner";
>	}
>}
>
>This prints "outer" (vax SVR2 compiler), though the for-while equivalence
>might lead one to expect "inner".
>
I don't understand why.  The value "inner" is associated with the variable
foo with scope inside the for loop (within the {}'s).  The value "outer"
is associated with the variable foo with scope outside the for loop (outside
the {}'s).  The printf(foo) is outside the for loop scope, so it should
print "outer".

-- 
-------------
Brett Galloway
{pesnta,twg,ios,qubix,turtlevax,tymix,vecpyr,certes,isi}!wjvax!brett

dant@tekla.UUCP (Dan Tilque) (09/05/86)

From: mikeb@copper.UUCP (Mike Beckerman)
>In article <15525@ucbvax.BERKELEY.EDU> ballou@brahms.UUCP (Kenneth R. Ballou) writes:
>>In article <86900030@haddock> karl@haddock writes:
>>>
>>>It's well known that the equivalence between for and while breaks down if
>>>there's a "continue" statement.  Here's another case I just discovered:
>>>
>>>main() {
>>>	char *foo = "outer";
>>>	for (;; printf(foo),exit(0)) {
>>>		char *foo = "inner";
>>>	}
>>>}
>>>
>>>This prints "outer" (vax SVR2 compiler), though the for-while equivalence
>>>might lead one to expect "inner".
>>
>>I don't think the issue here is equivalence of for and while statements.
>>The point is that the scope of the inner 'foo' is the compound statement
>>which is the body of the for statement.  So, quite rightly, the 'foo'
>>given as the argument to printf in the third expression of the for statement
>>refers to the most closely nested declaration of 'foo' -- the body of the
>>for statement is one block level higher and is not visible at this point.
>
>That was my first thought as well, but both K&R and the proposed ANSI C standard
>define the "for" loop as follows:
>
>	for (expression-1 ; expression-2 ; expression-3) statement
>
>		is equivalent to
>
>	expression-1;
>	while (expression-2) {
>		statement
>		expression-3;
>	}
>
>which to me says that the example should have printed "inner".
>

Ken Ballou is correct, and the equivalence above is correct.  The
equivalence of the first example is this:

main() {
	char *foo = "outer";
	while () { 
		{
			char *foo = "inner";
		}
	printf(foo),exit(0));
	}
}

The *foo = "inner" applies only within the inner braces (which 
delineate the statement).  The printf(foo) goes outside those braces.


 Dan Tilque		UUCP:		tektronix!dadla!dant
			CSnet:		dant%dadla@tektronix
			ARPAnet:	dant%dadla%tektronix@csnet-relay

 Mass extinction; it's not just for dinosaurs anymore.

karl@haddock (09/06/86)

pogo!operator (Shannon Nelson) writes:
>... The correct translation of your for loop into a while loop is:
>main() {
>        char *foo = "outer";
>        while (TRUE) {
>                { char *foo = "inner"; }
>                printf(foo);
>                exit(0);
>        }
>}

Oops.  You're right; I forgot about the extra braces.

But as long as we're on the subject, shouldn't the general whilified for be
written "{ e1; while (e2) { statement e3; } }", with the extra pair of braces
surrounding the whole mess?  (Consider "if (e0) for (e1; e2; e3) statement".)

Karl W. Z. Heuer (ima!haddock!karl; karl@haddock.isc.com), The Walking Lint