Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Scopes of identifiers Date: Fri, 12 Apr 2019 14:39:19 -0700 Organization: A noiseless patient Spider Lines: 91 Message-ID: <86imvij43c.fsf@mailhub.linuxsc.com> References: <098da5fe-31d3-47b7-b695-d4faea10b366@googlegroups.com> <5b59a4e9-81d3-4442-a9e6-6fa8419a08e7@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="5c14161f9027815e860f74bb47c27d06"; logging-data="25362"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX193DYWc/+mQO+w2ZZIFGqylCJzsi8a8gPM=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:5xtco8lPl1YAAolq5c28sFTFXSI= sha1:8y7ilJNvAeblCVe7TA9lTR1qI2o= Xref: csiph.com comp.lang.c:143063 Andrey Tarasevich writes: > On 4/11/2019 5:08 PM, Keith Thompson wrote: > >>> No. Nested blocks mean nested scopes in C. It does not matter >>> whether the block is "explicit" (a pair of `{}`) or "implicit" (as >>> described above). This immediately means that scopes associated >>> with nested blocks have different termination points. >> >> What are these two different termination points? > > The end of the "explicit" block and the end of the "implicit" > block. > >> Here's the code again: >> >> for (int i = 0; i < 10; ++i) >> { >> int i = 42; >> } >> >> There are two blocks here, one for the for statement and one for >> its body. N1570 6.8.5p5: >> >> 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. > > Exactly. The word *strict* is used in this text to emphasize the > fact that these blocks are nested, to emphasize the fact that they > are different. > >> One scope starts at the "for" keyword and ends at the "}" symbol. >> The other scope starts at the "{" symbol and ends at the "}" >> symbol. They start at different points, but they terminate at the >> same point. > > No, they don't. For some reason you are attempting to attach > beginning and termination points of blocks to some physical > characters in the source code. The language defines no such > attachment. Beginning and termination points are concepts. And > two different blocks always have two different termination points. > Pretty simple. > > One might claim that the document is underdefined, but to me it > looks like a stretch. The intent is perfectly clear: introduce > some extra ("implicit") blocks that envelop the existing blocks. > These extra blocks are "invisible" but otherwise behave just like > normal enveloping block do. I agree with your reading: the block of a controlling statement has a different (and larger) scope than those of its controlled statement(s). Note further that in C11 a small change in wording was made regarding scopes. In C99, 6.2.1 p4 said in part (italics in original in all cases) If so, the scope of one entity (the /inner scope/) will be a strict subset of the scope of the other entity (the /outer scope/). In C11, this sentence was changed to say If so, the scope of one entity (the /inner scope/) will end strictly before the scope of the other entity (the /outer scope/). IMO this change clarifies the "strict subset" wording used in the text in section 6.8 (Statements). Incidentally, note that the rules regarding "induced" blocks and their scopes are slightly different in C than in C++. For example, take the following function: int foo(){ extern unsigned bas(); for( unsigned x = bas(); x; x /= 2 ){ int x = 2; /* ... potentially more code here ... */ } return 0; } In C, this function definition is legal. In C++, the 'int x;' gets flagged as a redeclaration of 'x', even though it is enclosed in a compound statement. To me it looks like the C way is better. For one thing, this pattern can be used to guarantee that no modifications happen to the loop control variable within the loop body. Also I think the C++ way runs afoul of the Law of Least Astonishment.