Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #106792 > unrolled thread

for-loop scopes

Started byBartC <bc@freeuk.com>
First post2017-03-23 12:11 +0000
Last post2017-03-29 13:14 -0700
Articles 19 — 11 participants

Back to article view | Back to comp.lang.c


Contents

  for-loop scopes BartC <bc@freeuk.com> - 2017-03-23 12:11 +0000
    Re: for-loop scopes David Brown <david.brown@hesbynett.no> - 2017-03-23 14:14 +0100
      Re: for-loop scopes BartC <bc@freeuk.com> - 2017-03-23 13:45 +0000
        Re: for-loop scopes David Brown <david.brown@hesbynett.no> - 2017-03-23 15:48 +0100
        Re: for-loop scopes Robert Wessel <robertwessel2@yahoo.com> - 2017-03-23 23:01 -0500
          Re: for-loop scopes BartC <bc@freeuk.com> - 2017-03-24 10:27 +0000
            Re: for-loop scopes jameskuyper@verizon.net - 2017-03-24 10:43 -0700
            Re: for-loop scopes Robert Wessel <robertwessel2@yahoo.com> - 2017-03-26 21:57 -0500
    Re: for-loop scopes Keith Thompson <kst-u@mib.org> - 2017-03-23 08:37 -0700
    Re: for-loop scopes Ike Naar <ike@iceland.freeshell.org> - 2017-03-23 16:31 +0000
    Re: for-loop scopes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2017-03-23 10:23 -0700
      Re: for-loop scopes BartC <bc@freeuk.com> - 2017-03-23 18:07 +0000
        Re: for-loop scopes David Brown <david.brown@hesbynett.no> - 2017-03-23 20:05 +0100
        Re: for-loop scopes jameskuyper@verizon.net - 2017-03-23 12:33 -0700
        Re: for-loop scopes John Bode <jfbode1029@gmail.com> - 2017-03-24 11:35 -0700
    Re: for-loop scopes Noob <root@127.0.0.1> - 2017-03-23 21:06 +0100
    Re: for-loop scopes Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-03-28 19:15 -0700
      Re: for-loop scopes Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-03-28 19:19 -0700
      Re: for-loop scopes supercat@casperkitty.com - 2017-03-29 13:14 -0700

#106792 — for-loop scopes

FromBartC <bc@freeuk.com>
Date2017-03-23 12:11 +0000
Subjectfor-loop scopes
Message-ID<ob0drl$agb$1@dont-email.me>
This line in the 'struct padding' thread:

     for(long i = 0; i<N; i++)

prompted me to do more tests:

   {
     double i;                 // scope 1
     for (int i=0; i<10; ++i)  // scope 2
         i;                    // scope 2
         i;                    // scope 1, deliberate misalignment

Is is correct that the 'int i' inside the for-loop header creates a new 
scope for the following single statement, even without the existence of 
a formal {...} block?

I'm just asking because I'm finding it hard to believe that those last 
two final 'i' terms switch types with merely an intervening ';'.

-- 
bartc

[toc] | [next] | [standalone]


#106797

FromDavid Brown <david.brown@hesbynett.no>
Date2017-03-23 14:14 +0100
Message-ID<ob0hhm$n9j$1@dont-email.me>
In reply to#106792
On 23/03/17 13:11, BartC wrote:
> This line in the 'struct padding' thread:
> 
>     for(long i = 0; i<N; i++)
> 
> prompted me to do more tests:
> 
>   {
>     double i;                 // scope 1
>     for (int i=0; i<10; ++i)  // scope 2
>         i;                    // scope 2
>         i;                    // scope 1, deliberate misalignment
> 
> Is is correct that the 'int i' inside the for-loop header creates a new
> scope for the following single statement, even without the existence of
> a formal {...} block?

Yes.  See §6.8.5 and §6.8.5.3 in the standards (the bits covering the
"for statement").

> 
> I'm just asking because I'm finding it hard to believe that those last
> two final 'i' terms switch types with merely an intervening ';'.
> 

You don't think it odd that the first "i" is a statement expression
executed 10 times within the loop while the second "i" is executed
outside the loop - but you /do/ find it odd that the first "i" is in a
different scope from the second one?  That strikes me as a very strange
opinion.

[toc] | [prev] | [next] | [standalone]


#106799

FromBartC <bc@freeuk.com>
Date2017-03-23 13:45 +0000
Message-ID<ob0jcu$tuo$1@dont-email.me>
In reply to#106797
On 23/03/2017 13:14, David Brown wrote:
> On 23/03/17 13:11, BartC wrote:

>>     double i;                 // scope 1
>>     for (int i=0; i<10; ++i)  // scope 2
>>         i;                    // scope 2
>>         i;                    // scope 1, deliberate misalignment

>> I'm just asking because I'm finding it hard to believe that those last
>> two final 'i' terms switch types with merely an intervening ';'.
>>
>
> You don't think it odd that the first "i" is a statement expression
> executed 10 times within the loop while the second "i" is executed
> outside the loop

That's a little bit less odd, but then you know that C loop bodies might 
not end with a specific delimiter such as '}'; it could be just ';'

  - but you /do/ find it odd that the first "i" is in a
> different scope from the second one?  That strikes me as a very strange
> opinion.

Yes; that the first 'i' in 'i;i;' is an int, and the second might be a 
struct, is /more/ odd! You get used to scopes being delimited with {...}.

It is possible to have a scope end half-way through a block, but that is 
signalled by a new declaration at that point.

I suppose it is just necessary to imagine the entire for-loop, complete 
with body, enclosed in {...}.

-- 
bartc

[toc] | [prev] | [next] | [standalone]


#106803

FromDavid Brown <david.brown@hesbynett.no>
Date2017-03-23 15:48 +0100
Message-ID<ob0n26$bg7$1@dont-email.me>
In reply to#106799
On 23/03/17 14:45, BartC wrote:
> On 23/03/2017 13:14, David Brown wrote:
>> On 23/03/17 13:11, BartC wrote:
> 
>>>     double i;                 // scope 1
>>>     for (int i=0; i<10; ++i)  // scope 2
>>>         i;                    // scope 2
>>>         i;                    // scope 1, deliberate misalignment
> 
>>> I'm just asking because I'm finding it hard to believe that those last
>>> two final 'i' terms switch types with merely an intervening ';'.
>>>
>>
>> You don't think it odd that the first "i" is a statement expression
>> executed 10 times within the loop while the second "i" is executed
>> outside the loop
> 
> That's a little bit less odd, but then you know that C loop bodies might
> not end with a specific delimiter such as '}'; it could be just ';'
> 
>  - but you /do/ find it odd that the first "i" is in a
>> different scope from the second one?  That strikes me as a very strange
>> opinion.
> 
> Yes; that the first 'i' in 'i;i;' is an int, and the second might be a
> struct, is /more/ odd! You get used to scopes being delimited with {...}.
> 
> It is possible to have a scope end half-way through a block, but that is
> signalled by a new declaration at that point.
> 
> I suppose it is just necessary to imagine the entire for-loop, complete
> with body, enclosed in {...}.
> 

That is certainly a reasonable way to imagine it - and as far as scoping
is concerned, it is accurate.  There are a number of ways that scopes
are formed and limited, not just within {} blocks.  When programming in
C, it quickly becomes entirely obvious what the scope of identifiers is
- the scoping rules make a lot of sense, and work naturally.  If you
define an identifier inside the first clause of a "for" loop, then that
identifier's scope (and lifetime) covers the other clauses of the "for",
and the statement or block covered by the loop.  Anything else would be
counter-intuitive and less useful.

And when writing code, it makes sense to lay out your code in a manner
that matches the logic of the program.  So don't write:

	for (int i = 0; i < 10; ++)
		i;i;

That is much the same as writing a function:

	int timesTwo(int x) { return x * 3; }

It is legally correct C, but highly misleading to human programmers.  No
language can legislate against such practices - if you are going to
program in C, you have to learn to write sensible C code presented in a
sensible manner.

And for compiler development, you just have to read the rules in the
standards and obey them accurately - without jumping to fake rules about
brackets and scoping.

[toc] | [prev] | [next] | [standalone]


#106870

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-03-23 23:01 -0500
Message-ID<tp59dcd08sf50em2ts83i8us7jctt7j41h@4ax.com>
In reply to#106799
On Thu, 23 Mar 2017 13:45:47 +0000, BartC <bc@freeuk.com> wrote:

>On 23/03/2017 13:14, David Brown wrote:
>> On 23/03/17 13:11, BartC wrote:
>
>>>     double i;                 // scope 1
>>>     for (int i=0; i<10; ++i)  // scope 2
>>>         i;                    // scope 2
>>>         i;                    // scope 1, deliberate misalignment
>
>>> I'm just asking because I'm finding it hard to believe that those last
>>> two final 'i' terms switch types with merely an intervening ';'.
>>>
>>
>> You don't think it odd that the first "i" is a statement expression
>> executed 10 times within the loop while the second "i" is executed
>> outside the loop
>
>That's a little bit less odd, but then you know that C loop bodies might 
>not end with a specific delimiter such as '}'; it could be just ';'


Again you've invented an incorrect definition for these things, and
then reality makes no sense, or is excessively complex.  Try, for
example, to take your rules and apply them to:

  for(...)
     if (...)
        s;
     else
        for(...)
          {...}

Does the "}" on the last line terminate one loop? Two? The if?  The
last block? All of them (yes, FSVO of "yes").  How do you tell?  The
problem is that C does *not* have loop terminators, so if you've
defined the language in those terms, it doesn't work well.

"Loop bodies" as such in C are just (single) statements.  If you look
up the definition of "for", you find:

  for (expr1; expr2; expr3) statement

The definition of a statement, OTOH, is what's critical: a "statement"
is either a labeled-, compound-, expression-, selection, iteration- or
jump-statement.  In this case a compound statement is a {} block.

[toc] | [prev] | [next] | [standalone]


#106885

FromBartC <bc@freeuk.com>
Date2017-03-24 10:27 +0000
Message-ID<ob2s4l$o10$1@dont-email.me>
In reply to#106870
On 24/03/2017 04:01, Robert Wessel wrote:
> On Thu, 23 Mar 2017 13:45:47 +0000, BartC <bc@freeuk.com> wrote:
>
>> On 23/03/2017 13:14, David Brown wrote:
>>> On 23/03/17 13:11, BartC wrote:
>>
>>>>     double i;                 // scope 1
>>>>     for (int i=0; i<10; ++i)  // scope 2
>>>>         i;                    // scope 2
>>>>         i;                    // scope 1, deliberate misalignment
>>
>>>> I'm just asking because I'm finding it hard to believe that those last
>>>> two final 'i' terms switch types with merely an intervening ';'.
>>>>
>>>
>>> You don't think it odd that the first "i" is a statement expression
>>> executed 10 times within the loop while the second "i" is executed
>>> outside the loop
>>
>> That's a little bit less odd, but then you know that C loop bodies might
>> not end with a specific delimiter such as '}'; it could be just ';'
>
>
> Again you've invented an incorrect definition for these things, and
> then reality makes no sense, or is excessively complex.  Try, for
> example, to take your rules and apply them to:
>
>   for(...)
>      if (...)
>         s;
>      else
>         for(...)
>           {...}
>
> Does the "}" on the last line terminate one loop? Two? The if?  The
> last block? All of them (yes, FSVO of "yes").  How do you tell?  The
> problem is that C does *not* have loop terminators, so if you've
> defined the language in those terms, it doesn't work well.
>
> "Loop bodies" as such in C are just (single) statements.  If you look
> up the definition of "for", you find:
>
>   for (expr1; expr2; expr3) statement
>
> The definition of a statement, OTOH, is what's critical: a "statement"
> is either a labeled-, compound-, expression-, selection, iteration- or
> jump-statement.  In this case a compound statement is a {} block.
>

I don't think any of that contradicts what I said, which was:

(1) ... might not end with a specific delimiter such as }
(2) ... might end with just ;

As for being complex, I think you've just shown how complex it /can/ be 
trying to figure out what bit belongs to which previous bit.

(Or trying to work out why a {} compound statement doesn't need to end 
with ';', so making it possible to have {...}1234; as your last line. Or 
{...}{}{}{}. Look, no semicolons! That it just happens to be Written 
that way isn't an answer.)

-- 
bartc

[toc] | [prev] | [next] | [standalone]


#106959

Fromjameskuyper@verizon.net
Date2017-03-24 10:43 -0700
Message-ID<751f4f80-326f-4503-a7eb-d48b4599cfd2@googlegroups.com>
In reply to#106885
On Friday, March 24, 2017 at 6:27:24 AM UTC-4, Bart wrote:
> On 24/03/2017 04:01, Robert Wessel wrote:
...
> > Again you've invented an incorrect definition for these things, and
> > then reality makes no sense, or is excessively complex.  Try, for
> > example, to take your rules and apply them to:
> >
> >   for(...)
> >      if (...)
> >         s;
> >      else
> >         for(...)
> >           {...}
> >
> > Does the "}" on the last line terminate one loop? Two? The if?  The
> > last block? All of them (yes, FSVO of "yes").  How do you tell?  The
> > problem is that C does *not* have loop terminators, so if you've
> > defined the language in those terms, it doesn't work well.
> >
> > "Loop bodies" as such in C are just (single) statements.  If you look
> > up the definition of "for", you find:
> >
> >   for (expr1; expr2; expr3) statement
> >
> > The definition of a statement, OTOH, is what's critical: a "statement"
> > is either a labeled-, compound-, expression-, selection, iteration- or
> > jump-statement.  In this case a compound statement is a {} block.
> >
> 
> I don't think any of that contradicts what I said, which was:
>
> (1) ... might not end with a specific delimiter such as }
> (2) ... might end with just ;
> 
> As for being complex, I think you've just shown how complex it /can/ be 
> trying to figure out what bit belongs to which previous bit.

Not really. It shows how simple it is to figure you which bit belongs with which
previous bit.

The body of the first for statement must be a single statement. The only
statement that's in the correct location to qualify is the if() statement. The
if-statement takes one statement as it's if-clause, and optionally another
statement as it's else clause. The only statements in the right positions to
qualify are "s;" and the second for-statement. The only statement in the right
position to be the body of second for-statement is the compound statement that
follows it.

> (Or trying to work out why a {} compound statement doesn't need to end 
> with ';',

That's because there's no general requirement that statements end in ';'.
expression-statements, null-statements, do-while statements, and jump statements
all end with ';'. Compound statements do not, because the '}' is sufficient to
identify the end of the compound statement. All of the other types of statements
have an arbitrary sub-statement as the last component of that statement. Whether
they end in a ';' or a '}' depends entirely upon whether the (recursively)
terminal statement is a compound statement or one of the other types.

> ... so making it possible to have {...}1234; as your last line. Or 
> {...}{}{}{}. Look, no semicolons! That it just happens to be Written 
> that way isn't an answer.)

The reason is simply that compound statements don't need a ';' to terminate
them, the '}' does that job quite adequately. I'm not saying that this true
because the standard says so, I'm saying that this is the reason why the
standard says so (and of course, it's long pre-dates the standard, being an
aspect of some of C's predecessor languages).

Don't have your parser look for ';' to terminate statements, and them make a
special exception for compound statements. Simply have your parser know and
implement the grammar rules for each statement type, being well aware that some
of them don't necessarily end with a ';'.

[toc] | [prev] | [next] | [standalone]


#107131

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-03-26 21:57 -0500
Message-ID<jqvgdchac3g2qg4j28ddd9og1e0isk887r@4ax.com>
In reply to#106885
On Fri, 24 Mar 2017 10:27:13 +0000, BartC <bc@freeuk.com> wrote:

>On 24/03/2017 04:01, Robert Wessel wrote:
>> On Thu, 23 Mar 2017 13:45:47 +0000, BartC <bc@freeuk.com> wrote:
>>
>>> On 23/03/2017 13:14, David Brown wrote:
>>>> On 23/03/17 13:11, BartC wrote:
>>>
>>>>>     double i;                 // scope 1
>>>>>     for (int i=0; i<10; ++i)  // scope 2
>>>>>         i;                    // scope 2
>>>>>         i;                    // scope 1, deliberate misalignment
>>>
>>>>> I'm just asking because I'm finding it hard to believe that those last
>>>>> two final 'i' terms switch types with merely an intervening ';'.
>>>>>
>>>>
>>>> You don't think it odd that the first "i" is a statement expression
>>>> executed 10 times within the loop while the second "i" is executed
>>>> outside the loop
>>>
>>> That's a little bit less odd, but then you know that C loop bodies might
>>> not end with a specific delimiter such as '}'; it could be just ';'
>>
>>
>> Again you've invented an incorrect definition for these things, and
>> then reality makes no sense, or is excessively complex.  Try, for
>> example, to take your rules and apply them to:
>>
>>   for(...)
>>      if (...)
>>         s;
>>      else
>>         for(...)
>>           {...}
>>
>> Does the "}" on the last line terminate one loop? Two? The if?  The
>> last block? All of them (yes, FSVO of "yes").  How do you tell?  The
>> problem is that C does *not* have loop terminators, so if you've
>> defined the language in those terms, it doesn't work well.
>>
>> "Loop bodies" as such in C are just (single) statements.  If you look
>> up the definition of "for", you find:
>>
>>   for (expr1; expr2; expr3) statement
>>
>> The definition of a statement, OTOH, is what's critical: a "statement"
>> is either a labeled-, compound-, expression-, selection, iteration- or
>> jump-statement.  In this case a compound statement is a {} block.
>>
>
>I don't think any of that contradicts what I said, which was:
>
>(1) ... might not end with a specific delimiter such as }
>(2) ... might end with just ;
>
>As for being complex, I think you've just shown how complex it /can/ be 
>trying to figure out what bit belongs to which previous bit.
>
>(Or trying to work out why a {} compound statement doesn't need to end 
>with ';', so making it possible to have {...}1234; as your last line. Or 
>{...}{}{}{}. Look, no semicolons! That it just happens to be Written 
>that way isn't an answer.)


Perhaps because you're doing it wrong.

[toc] | [prev] | [next] | [standalone]


#106807

FromKeith Thompson <kst-u@mib.org>
Date2017-03-23 08:37 -0700
Message-ID<ln1stoats8.fsf@kst-u.example.com>
In reply to#106792
BartC <bc@freeuk.com> writes:
> This line in the 'struct padding' thread:
>
>      for(long i = 0; i<N; i++)
>
> prompted me to do more tests:
>
>    {
>      double i;                 // scope 1
>      for (int i=0; i<10; ++i)  // scope 2
>          i;                    // scope 2
>          i;                    // scope 1, deliberate misalignment
>
> Is is correct that the 'int i' inside the for-loop header creates a new 
> scope for the following single statement, even without the existence of 
> a formal {...} block?

Did you try looking it up in the standard before posting?  Why not?

> I'm just asking because I'm finding it hard to believe that those last 
> two final 'i' terms switch types with merely an intervening ';'.

If your code layout is deliberately misleading, it's going to lead to
surprises.  Not all scopes are delimited by curly braces.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#106812

FromIke Naar <ike@iceland.freeshell.org>
Date2017-03-23 16:31 +0000
Message-ID<slrn3vfsod7u80.65h.ike@iceland.freeshell.org>
In reply to#106792
On 2017-03-23, BartC <bc@freeuk.com> wrote:
>    {
>      double i;                 // scope 1
>      for (int i=0; i<10; ++i)  // scope 2
>          i;                    // scope 2
>          i;                    // scope 1, deliberate misalignment
>
> Is is correct that the 'int i' inside the for-loop header creates a new 
> scope for the following single statement, even without the existence of 
> a formal {...} block?
>
> I'm just asking because I'm finding it hard to believe that those last 
> two final 'i' terms switch types with merely an intervening ';'.

It's not the case that 'i' switches types.
The two 'i'-s just denote different objects.
Their types could be the same and they would still denote different objects:

  int i; /* scope 1 */
  for (int i = 0; i != 10; ++i) i; /* scope 2 */
  i; /* scope 1 */

[toc] | [prev] | [next] | [standalone]


#106818

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2017-03-23 10:23 -0700
Message-ID<828e6fda-e420-4060-9339-0e699adfffd0@googlegroups.com>
In reply to#106792
On Thursday, March 23, 2017 at 8:11:26 AM UTC-4, Bart wrote:
> This line in the 'struct padding' thread:
> 
>      for(long i = 0; i<N; i++)
> 
> prompted me to do more tests:
> 
>    {
>      double i;                 // scope 1
>      for (int i=0; i<10; ++i)  // scope 2
>          i;                    // scope 2
>          i;                    // scope 1, deliberate misalignment
> 
> Is is correct that the 'int i' inside the for-loop header creates a new 
> scope for the following single statement, even without the existence of 
> a formal {...} block?
> 
> I'm just asking because I'm finding it hard to believe that those last 
> two final 'i' terms switch types with merely an intervening ';'.

As Ike Naar points out, it doesn't switch types.  There are two
isolated scopes, and the names referenced within result in access
to two completely isolated variables:

    Local variable scope:
       |    +------------+
       +===>| double | i |
       |    +------------+
       |
       +===>For-loop inner scope:
               |    +------------+
               +===>| int    | i |
                    +------------+

And if you had a second inner loop:

    Local variable scope:
       |    +------------+
       +===>| double | i |
       |    +------------+
       |
       +===>For-loop inner scope:
               |    +------------+
               +===>| int    | i |
               |    +------------+
               |
               +===>For-loop inner-inner scope:
                       |    +------------+
                       +===>| int    | i |
                            +------------+

... and so on ...

When your "i" variable is referenced in code, depending on what
scope you're in at the time, the compiler will search upward in
the hierarchy of scopes and find the one that matches.  If it
doesn't find the name in its scope, go up one.  If it's not found
there, go up one.  And repeat until all scopes are exhausted or
it's found.

Each inner scope effectively hides access to the variables of the
same name in higher scopes.  So, not only are tokens identified by
their name, but also by their locality.

-----
In your compiler, you surely have mechanisms to perform this kind
of search up the chain of scopes to find the suitable match?  I
was very surprised by your question.

Thank you,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#106829

FromBartC <bc@freeuk.com>
Date2017-03-23 18:07 +0000
Message-ID<ob12nn$o7g$1@dont-email.me>
In reply to#106818
On 23/03/2017 17:23, Rick C. Hodgin wrote:

> In your compiler, you surely have mechanisms to perform this kind
> of search up the chain of scopes to find the suitable match?  I
> was very surprised by your question.

The mechanism for resolving names is there. What wasn't there was a 
mechanism for inventing impromptu scopes out of nowhere!

A C for-statement doesn't have the concept of a controlling loop 
variable, but it does now have a private scope...

-- 
bartc

[toc] | [prev] | [next] | [standalone]


#106841

FromDavid Brown <david.brown@hesbynett.no>
Date2017-03-23 20:05 +0100
Message-ID<ob1646$6ae$1@dont-email.me>
In reply to#106829
On 23/03/17 19:07, BartC wrote:
> On 23/03/2017 17:23, Rick C. Hodgin wrote:
>
>> In your compiler, you surely have mechanisms to perform this kind
>> of search up the chain of scopes to find the suitable match?  I
>> was very surprised by your question.
>
> The mechanism for resolving names is there. What wasn't there was a
> mechanism for inventing impromptu scopes out of nowhere!
>
> A C for-statement doesn't have the concept of a controlling loop
> variable, but it does now have a private scope...
>

Yes.  And it works extremely well.  /Most/ for loops have a single 
controlling variable, and you can define it within the for loop so that 
it has exactly the scope it needs - and no more.  But you still have the 
flexibility that C's for loop gives you if you want.  The ability to 
declare your loop variable inside the for statement is, I think, a 
particularly nice feature of C99.

[toc] | [prev] | [next] | [standalone]


#106843

Fromjameskuyper@verizon.net
Date2017-03-23 12:33 -0700
Message-ID<1638e344-efec-45f2-ac8d-4dd2e3061632@googlegroups.com>
In reply to#106829
On Thursday, March 23, 2017 at 2:07:43 PM UTC-4, Bart wrote:
> On 23/03/2017 17:23, Rick C. Hodgin wrote:
> 
> > In your compiler, you surely have mechanisms to perform this kind
> > of search up the chain of scopes to find the suitable match?  I
> > was very surprised by your question.
> 
> The mechanism for resolving names is there. What wasn't there was a 
> mechanism for inventing impromptu scopes out of nowhere!
> 
> A C for-statement doesn't have the concept of a controlling loop 
> variable, but it does now have a private scope...
> 
> -- 
> bartc

"If the declarator or type specifier that declares the identifier appears inside
a block or within the list of parameter declarations in a function definition,
the identifier has block scope, which terminates at the end of the associated
block." (6.2.1p4)

6.8p5 describes iteration statements, which include, in particuar, for
statements.

"An iteration statement is a block whose scope is a strict subset of the scope
of its enclosing block. The loop body is also a block whose scope is a strict
subset of the scope of the iteration statement." (6.8.5p5)

It's only the first sentence that is new in C99. Since both scopes end in the
same location (at the end of the loop body), they are considered to be the same
scope (6.2.1p6). Therefore, the scope that you're complaining about is not new
in C99, it's just bigger than it was in C90.

What does "private scope" mean to you? As far as C is concerned, there's no
distinction between this scope and any other kind of block scope.

[toc] | [prev] | [next] | [standalone]


#106976

FromJohn Bode <jfbode1029@gmail.com>
Date2017-03-24 11:35 -0700
Message-ID<bbc37a81-3eae-46eb-ab8e-6220a585a322@googlegroups.com>
In reply to#106829
On Thursday, March 23, 2017 at 1:07:43 PM UTC-5, Bart wrote:
> On 23/03/2017 17:23, Rick C. Hodgin wrote:
> 
> > In your compiler, you surely have mechanisms to perform this kind
> > of search up the chain of scopes to find the suitable match?  I
> > was very surprised by your question.
> 
> The mechanism for resolving names is there. What wasn't there was a 
> mechanism for inventing impromptu scopes out of nowhere!
> 
> A C for-statement doesn't have the concept of a controlling loop 
> variable, but it does now have a private scope...
> 
> -- 
> bartc

Why is this surprising?  

> 6.8.5.3 The for statement
> 1 The statement 
>  
>    for ( clause-1 ; expression-2 ; expression-3 ) statement
> 
> behaves as follows: The expression expression-2 is the controlling 
> expression that is evaluated before each execution of the loop body. 
> The expression expression-3 is evaluated as a void expression after 
> each execution of the loop body. **IF CLAUSE-1 IS A DECLARATION, THE
> SCOPE OF ANY IDENTIFIERS IT DECLARES IS THE REMAINDER OF THE DECLARATION 
> AND THE ENTIRE LOOP, INCLUDING THE OTHER TWO EXPRESSIONS;** it is reached 
> in the order of execution before the first evaluation of the controlling 
> expression. If clause-1 is an expression, it is evaluated as a void 
> expression before the first evaluation of the controlling expression.158)

[toc] | [prev] | [next] | [standalone]


#106848

FromNoob <root@127.0.0.1>
Date2017-03-23 21:06 +0100
Message-ID<ob19mb$jlm$1@dont-email.me>
In reply to#106792
On 23/03/2017 13:11, BartC wrote:

> This line in the 'struct padding' thread:
> 
>      for(long i = 0; i<N; i++)
> 
> prompted me to do more tests:

http://port70.net/~nsz/c/c11/n1570.html#6.8.5
http://port70.net/~nsz/c/c11/n1570.html#6.8.5.3

[toc] | [prev] | [next] | [standalone]


#107356

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2017-03-28 19:15 -0700
Message-ID<obf57d$r48$1@dont-email.me>
In reply to#106792
On 3/23/2017 5:11 AM, BartC wrote:
> This line in the 'struct padding' thread:
>
>     for(long i = 0; i<N; i++)
>
> prompted me to do more tests:
>
>   {
>     double i;                 // scope 1
>     for (int i=0; i<10; ++i)  // scope 2
>         i;                    // scope 2
>         i;                    // scope 1, deliberate misalignment
>
> Is is correct that the 'int i' inside the for-loop header creates a new
> scope for the following single statement, even without the existence of
> a formal {...} block?
>
> I'm just asking because I'm finding it hard to believe that those last
> two final 'i' terms switch types with merely an intervening ';'.
>

Yes it does. Actually, it creates two: one for the whole 'for' statement 
and another, nested one for the loop body. This is related to one of the 
changes in C99.

In C89/90 the only way to create a local scope was to use an explicit 
pair of '{ ... }'. There is simply no reason to create any "implicit" 
local scopes in C89/90. (Primarily because declarations in C are not 
statements, and therefore "unenclosed" object definitions cannot be used 
as a body of 'for', 'while', 'switch', branches of 'if' etc.). Since 
naked object definition cannot be used as a body of 'for', there's no 
issue of limiting its lifetime, there's no need for implicit blocks. End 
of story.

So, in C89/90 your 'for' does not create a local scope for its body. 
This can be verified (and/or exploited) by the following code

     int i;
     for (i = 0; i < 10; ++i)
       sizeof(enum { A });

     i = A;
     /* OK, sees 'A' declared inside 'for' */

     if (sizeof(enum { B }) > 0)
       sizeof(enum { C });
     else
       sizeof(enum { D });

     i = A + B + C + D;
     /* OK, sees 'B', 'C' and 'D' declared inside 'if' */

This code will happily compile in C89/90 mode, i.e. fresh enum constant 
declarations introduced inside the body of 'for', condition and branches 
of 'if' are visible after those statements.

In C99 declarations are not a statements either, but C99 introduced 
_compound literals_. And compound literals brought with them the same 
lifetime issues object definitions would, since compound literals are 
basically definitions of nameless objects. E.g. in this code

     int *p;
     for (i = 0; i < 10; ++i)
       p = (int []) { rand(); }

Should `p` remain valid after the loop? If yes, then this cycle should 
generally spawn 10 compound literals, all of which should remain alive 
till the end of the enclosing block.

C99 decided that this is not how it should work. Instead, lifetime of 
compound literals created in such contexts is limited (in C++ fashion) 
to the confines of an _implicit_ block that now encloses the loop body 
and another implicit block that encloses the whole loop. Similar 
implicit blocks now surround each branch of 'if' and enclose the whole 
'if' as well.

The above code sample with enum declarations made inside 'sizeof' no 
longer compiles in C99.

-- 
Best regards,
Andrey Tarasevich

[toc] | [prev] | [next] | [standalone]


#107357

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2017-03-28 19:19 -0700
Message-ID<obf5el$r48$2@dont-email.me>
In reply to#107356
On 3/28/2017 7:15 PM, Andrey Tarasevich wrote:
> basically definitions of nameless objects. E.g. in this code
>
>     int *p;
>     for (i = 0; i < 10; ++i)
>       p = (int []) { rand(); }
>

Typos... Should be

     int *p;
     for (int i = 0; i < 10; ++i)
       p = (int []) { rand() };

-- 
Best regards,
Andrey Tarasevich

[toc] | [prev] | [next] | [standalone]


#107416

Fromsupercat@casperkitty.com
Date2017-03-29 13:14 -0700
Message-ID<71b07a81-b66c-40eb-8d20-566d53654589@googlegroups.com>
In reply to#107356
On Tuesday, March 28, 2017 at 9:16:07 PM UTC-5, Andrey Tarasevich wrote:
> Should `p` remain valid after the loop? If yes, then this cycle should 
> generally spawn 10 compound literals, all of which should remain alive 
> till the end of the enclosing block.

Or the Standard could have said that the lifetime of a compound literal
object will end either when code leaves the enclosing function or the
next time the expression is creating it is evaluated, whichever happens
first [thus allowing a compiler to reuse objects or not at its leisure].

> C99 decided that this is not how it should work. Instead, lifetime of 
> compound literals created in such contexts is limited (in C++ fashion) 
> to the confines of an _implicit_ block that now encloses the loop body 
> and another implicit block that encloses the whole loop. Similar 
> implicit blocks now surround each branch of 'if' and enclose the whole 
> 'if' as well.

A mistake, IMHO, especially given the lack of static compound literals.
I could see making the lifetime of compound literals end at the current
context's next sequence point following their evaluation (meaning that
the address-of operator would basically only be useful when passing a
literal into a function), or extending it as described above.  Extending
it to the enclosing block means that something like:

   someStructType *p = 0;

   while(...)
   {
     if (someCondition && (!p || (p = &(someStructType)(...values...))))
     {
     }
   }

would yield correct semantics, but enclosing the "if" statement within a
block would break it.  I can't really think of cases where extending the
literal's lifetime past the next sequence point in the context where it
is created would be necessary and sufficient for code that wasn't very
brittle.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web