Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #106792 > unrolled thread
| Started by | BartC <bc@freeuk.com> |
|---|---|
| First post | 2017-03-23 12:11 +0000 |
| Last post | 2017-03-29 13:14 -0700 |
| Articles | 19 — 11 participants |
Back to article view | Back to comp.lang.c
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
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-03-23 12:11 +0000 |
| Subject | for-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | jameskuyper@verizon.net |
|---|---|
| Date | 2017-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | Ike Naar <ike@iceland.freeshell.org> |
|---|---|
| Date | 2017-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]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2017-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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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]
| From | jameskuyper@verizon.net |
|---|---|
| Date | 2017-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]
| From | John Bode <jfbode1029@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Noob <root@127.0.0.1> |
|---|---|
| Date | 2017-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]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2017-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]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2017-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-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