8

The C spec says

There are four kinds of scopes: function, file, block, and function prototype.

Now if I do the following outside any function

struct A {
  int x;
};

My understanding is that the identifier x is visible at file-scope. And that we use a namespace syntax to access the member, as the spec says

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)

Let's make this more clearer by adding a function

struct A {
  int x;
};

void f(void) {
  int i;
}

Then the identifiers, scopes and namespaces participating in this program's representation are (N/A is "not applicable"):

file scope
==========================================
Ordinary  |  Members A  |  Tags  |  Labels
------------------------------------------
 f        | x           | A      | N/A
          |             |        |


function scope of f
=========================================
Ordinary  |  Members ? |  Tags  |  Labels
-----------------------------------------
 N/A      | N/A        | N/A    |
          |            |        |


block scope #1
=========================================
Ordinary  |  Members ? |  Tags  |  Labels
-----------------------------------------
 i        |            |        | N/A
          |            |        |

And the scope hierarchy is "block scope #1" -> "function scope of f" -> "file scope".

I once talked with a C compiler writer, and he said that x is not into any scope. Can anyone please explain how this would work? How could we refer to x in any way at all then? Further quotation (emphasize mine):

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.

If we say that a member of a struct has no scope, then it is not visible and therefor cannot be used. But obviously, we can use struct members. Am I missing anything?

Community
  • 1
  • 1
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212

4 Answers4

5

As the standard says, it's in a separate name space created for the struct type. This rule was added in C89, I think. Once upon a time, all member names shared a single name space.

Maybe the compiler writer was being pedantic; a name space is not the same as a scope. A struct definition does not introduce a scope as it doesn't hold variables; it holds members.

Community
  • 1
  • 1
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • Is my table diagram wrong? I wonder whether the nesting is the other way around (i.e namespace, and within the namespaces, there are scopes). Because the spec says once " If an identifier designates two different entities in the same name space, the scopes might overlap.", which seems to indicate my nesting is wrong, because it indicates each scope's namespaces are distinct from each other scope's namespaces. How to solve this? – Johannes Schaub - litb Mar 11 '11 at 17:52
0

I think the scope it refers to in this case is A. You refer to the member by SomeA.x, where SomeA is of type A.

reuscam
  • 1,841
  • 2
  • 18
  • 23
0

x is in the scope created by struct A, but A is in global scope. This is what the "spec" calls file-scope but the name is misleading because all files that you include share that scope.

Bernd Elkemann
  • 23,242
  • 4
  • 37
  • 66
0

Scope and name space are two entirely different concepts and should not be confused.

An instance of a struct or union has scope, but the individual member names do not; the concept of scope simply doesn't apply to them.

Argh, I was thinking in terms of extent, not scope.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • a label has function scope, and we refer to it by `goto labelname`. A struct member has the scope of its struct tag (i.e block, file or function prototype, depending on where the struct was declared), and we refer to it by `instance.membername`. Why is this not the case? If the membername is not in scope anywhere, how can we refer to the member at all? – Johannes Schaub - litb Mar 11 '11 at 18:37
  • I just edited my answer; I was thinking in terms of extent, not scope. However, I still think you're conflating concepts that should not be conflated, but I lack the skill to explain exactly why. – John Bode Mar 11 '11 at 18:42