"
An identifier can denote an object; a function; a tag or a member of a
structure, union, or enumeration; a typedef name; a label name; a macro
name; or a macro parameter.
The same identifier can denote different entities at different points in the
program.
For each different entity that an identifier designates, the identifier is
visible (i.e., can be used) only within a region of program text called its
scope.
"
and
"
If more than one declaration of a particular identifier is visible at any
point in a translation unit, the syntactic context disambiguates uses that
refer to different entities. Thus, there are separate name spaces for
various categories of identifiers, as follows: [...]
- the members of structures or unions; each structure or union has a
separate name space for its members (disambiguated by the type of the
expression used to access the member via the . or -> operator);
"
Does all that mean that struct members have a scope? Does the following
program declare "x" to have file scope?
struct A {
int x;
};
int main(void) {
}
Some people told me that struct members don't have any scope. But if they
don't have the scope, they are not visible, and if they are not visible,
they cannot be used. But obviously, we can use them. How do struct members
interact with scope?
> "Johannes Schaub (litb)" <schaub....@googlemail.com> writes:
>>Does all that mean that struct members have a scope? Does the following
>>program declare "x" to have file scope?
>>struct A {
>> int x;
>
> Structure, union, and enumeration tags have scope that
> begins just after the appearance of the tag in a type
> specifier that declares the tag.
Huh?
>The C spec says
>
>"
>An identifier can denote an object; a function; a tag or a member of a
>structure, union, or enumeration; a typedef name; a label name; a macro
>name; or a macro parameter.
>
>The same identifier can denote different entities at different points in the
>program.
>
>For each different entity that an identifier designates, the identifier is
>visible (i.e., can be used) only within a region of program text called its
>scope.
Why did you stop quoting here. In two more paragraphs, the answer to
your question is explicitly stated.
>"
>
>and
>
>"
>If more than one declaration of a particular identifier is visible at any
>point in a translation unit, the syntactic context disambiguates uses that
>refer to different entities. Thus, there are separate name spaces for
>various categories of identifiers, as follows: [...]
>- the members of structures or unions; each structure or union has a
>separate name space for its members (disambiguated by the type of the
>expression used to access the member via the . or -> operator);
>"
Why did you bother quoting this. Name space is a different concept
from scope. These paragraphs have nothing to do with your question.
>
>Does all that mean that struct members have a scope? Does the following
>program declare "x" to have file scope?
>
>struct A {
> int x;
>};
>
>int main(void) {
>}
An identifier can denote a member of a structure (6.2.1-1)
Every other identifier [not a label name described in the previous
paragraph] has scope (6.2.1-4).
Therefore x has scope regardless of what people tell you.
Since the declaration for x appears outside of any block or list of
parameters, it has file scope (also 6.2.1-4)
Where do find any room to dispute this?
>
>Some people told me that struct members don't have any scope. But if they
>don't have the scope, they are not visible, and if they are not visible,
It is possible that this is the first time someone has told you
something incorrect but you can bet the rent it won't be the last.
>they cannot be used. But obviously, we can use them. How do struct members
>interact with scope?
Exactly as the standard says they do.
--
Remove del for email
That's a direct quotation from the standard, 6.2.1p7.
For example:
{
struct this_is_the_tag {
int x;
};
struct this_is_the_tag obj;
}
The token sequence "struct this_is_the_tag { int x; }" is a type
specifier; it declares the tag "this_is_the_tag". The scope of
"this_is_the_tag" begins just after the appearance of its name,
and ends at the last "}", i.e., at the end of the block.
This means that, for example, you can use use the name
"this_is_the_tag" inside the struct declaration:
{
struct this_is_the_tag {
int x;
struct this_is_the_tag *next;
};
struct this_is_the_tag obj;
}
It's no longer visible (it's out of scope) after the final closing "}".
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Indeed, but what does it have to do with the question?
It doesn't need to be. Note the last sentence:
Structure, union, and enumeration tags have scope that begins
just after the appearance of the tag in a type specifier that
declares the tag. Each enumeration constant has scope that
begins just after the appearance of its defining enumerator
in an enumerator list. Any other identifier has scope that
begins just after the completion of its declarator.
I'm not sure whether the declarator in question is the declaration
of the member or of the struct or union. It might not matter;
I can't think of a legal way to use the name of a struct member
prior to the end of the struct declaration that contains it.
Yes, and yes.
> struct A {
> int x;
> };
>
> int main(void) {
> }
>
> Some people told me that struct members don't have any scope. But if they
> don't have the scope, they are not visible, and if they are not visible,
> they cannot be used. But obviously, we can use them. How do struct members
> interact with scope?
6.2.1p1: "An identifier can denote ... a member of a structure, union,
or enumeration ..."
p2 describes the scope of identifiers which are statement labels.
p3: "Every other identifier has scope determined by the placement of its
declaration (in a declarator or type specifier). If the declarator or
type specifier that declares the identifier appears outside of any block
or list of parameters, the identifier has file scope, which
terminates at the end of the translation unit. 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. If the declarator or type specifier that declares the
identifier appears within the list of parameter declarations in a
function prototype (not part of a function definition), the identifier
has function prototype scope, which terminates at the end of the
function declarator."
p7: after discussing tags and enumeration constants, it says "Any
other identifier has scope that begins just after the completion of its
declarator."
Example:
struct one{
int file_scope_member/* scope starts here */, another;
};
void func(
struct two {
int prototype_scope_member/* scope starts here */,
yet_another;
},
int
/* scope of prototype_scope_member ends here */);
int main(void)
{
struct three{
int block_scope_member/* scope starts here */, the_last_one;
}
return 0;
/* Scope of block_scope_member ends here */}
/* Scope of file_scope_member ends here */
--
James Kuyper
You're using "scope" for two notions that the Standard calls
"scope" and "name space." The identifier `b' is in scope everywhere
after its declaration -- including inside main() -- but has meaning
only in the name space of `struct a'. See 6.2.3.
--
Eric Sosman
eso...@ieee-dot-org.invalid
Not much; I didn't look closely enough at the context.
The Standard introduces the concept of "namespaces" as merely a syntactic
construct to disambiguate uses, and not as a semantic entity that somehow
"contains" identifiers.
What does "in the namespace" mean?
> r...@zedat.fu-berlin.de (Stefan Ram) writes:
>>»the identifier is visible (i.e., can be used) only
>>within a region of program text called its scope.«,
>
> For example,
>
> struct a { int b; }; int main( void ){ b; }
>
> test.c:1: error: 'b' undeclared (first use in this function)
>
> , doesn't sound as if »b« would be visible in main.
>
> But, of course, gcc is just a compiler.
>
> But ISO/IEC 9899:1999 (E) even explains »visible«:
> »can be used« (see quotation above).
>
> »b« cannot be used in main above.
>
> We could add »a.« in front of »b« - but then it would
> be another program, so assertions about the scope in
> this other program would not be valid for the program
> above.
No, "b" can be used in "main". But if you just do "b;", it will look into
the ordinary namespace for identifiers. You have to use an "a." or "a->" to
make it look into the struct-A members namespace of the global scope to use
"b" in main.
Just like you have to use "struct a" to use the identifier "a" in main,
which is in the tags namespace of the global scope.
Ah I think I get this now. The name spaces divide a scope into multiple
sections.
Sounds like a challenge. How about:
struct foo *x;
struct foo {
int a;
char b[ sizeof x->a ];
};
gcc didn't like it; I haven't gone through the standard yet to see if
there's any language to explicitly allow or disallow this.
--
poncho
Interesting. This seems to be allowed/not forbidden.
Assuming there isn't any text that forbids it, surely
that's just an oversight in the Standard. The operators
'.' and '->' are expected to require complete types, no?
There is no reason why they should require a complete type, even
though many compilers reject the above code. Referring to a previously
declared member of a not yet completed structure type is possible in
theory, and at least one compiler permits it: OpenWatcom gives no
error, warning, or any other diagnostic for it.
I filed a report on clang: http://llvm.org/bugs/show_bug.cgi?id=9471
> On Mar 12, 7:15 pm, Tim Rentsch <t...@alumni.caltech.edu> wrote:
>> "Johannes Schaub (litb)" <schaub.johan...@googlemail.com> writes:
>> > Scott Fluhrer wrote:
>> >> Sounds like a challenge. How about:
>>
>> >> struct foo *x;
>>
>> >> struct foo {
>> >> int a;
>> >> char b[ sizeof x->a ];
>> >> };
>>
>> >> gcc didn't like it; I haven't gone through the standard yet to see if
>> >> there's any language to explicitly allow or disallow this.
>>
>> > Interesting. This seems to be allowed/not forbidden.
>>
>> Assuming there isn't any text that forbids it, surely
>> that's just an oversight in the Standard. The operators
>> '.' and '->' are expected to require complete types, no?
>
> There is no reason why they should require a complete type, even
> though many compilers reject the above code.
I meant 'require' in the sense of 'only guaranteed to be defined
for'.
> Referring to a previously
> declared member of a not yet completed structure type is possible in
> theory, and at least one compiler permits it: OpenWatcom gives no
> error, warning, or any other diagnostic for it.
And this behavior is reasonable, or at least permissible, if such
cases were specified as undefined behavior, which is how I expect
the Standard would specify it. So too is giving an error message
and refusing to proceed.