7

I have just discovered that both gcc and clang accept the following code:

typedef int blah;
struct s { char blah; };

However, they reject this, since a type name is being used as an identifier:

typedef int blah;
char blah;

Does this mean that the typedef'd name is not visible inside the struct definition? No, because this works in both gcc and clang:

typedef int blah;
struct s { blah blah; }

I am looking in the C99 standard and can't find anything which clarifies why a typedef'd name can be used as the name of a struct member, but not of a variable in the same scope.

Can someone explain why this is? A reference to any applicable standard would be appreciated.

Alex D
  • 29,755
  • 7
  • 80
  • 126
  • 3
    In the first snippet `blah` is a struct member name, in the second snippet `blah` is a variable name, that's two very different things. – Jabberwocky Apr 29 '20 at 14:46
  • [This question](https://stackoverflow.com/q/43134404/1233251) might answer your own, although its quality is subpar. – E_net4 Apr 29 '20 at 14:46
  • the same reason you could do `int var; struct foo bar; bar.var = var;` – S.S. Anne Apr 29 '20 at 14:59
  • @Jabberwocky Thanks for the comment. Do you know if there is anything in any C standard which clarifies how those two things behave as respect to names which are already typedef'd in the same scope? I'm reading the standard and haven't seen anything that suggests there would be any difference. – Alex D Apr 29 '20 at 15:32
  • Please, be clear, do gcc and clang accept or reject that? – Luis Colorado Apr 30 '20 at 19:52
  • @LuisColorado, they both accept the code which the question says "works". – Alex D May 01 '20 at 09:33

2 Answers2

9

Members of structures and ordinary variables are in different namespaces. That's why having two ordinary variables with same identifier name fails whereas if the same identifier name is used in a struct member and an ordinary variable is fine.

The C standard defines distinct namespaces:

6.2.3 Name spaces of identifiers

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:

  • label names (disambiguated by the syntax of the label declaration and use);
  • the tags of structures, unions, and enumerations (disambiguated by following any32) of the keywords struct, union, or enum);
  • 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);
  • all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumeration constants).

(The last two bullet items directly address this question)

Yes, typedef'ed identifiers share the name space with ordinary identifiers. 6.7.8 Type definitions:

[...] A typedef name shares the same name space as other identifiers declared in ordinary declarators.

user3386109
  • 34,287
  • 7
  • 49
  • 68
P.P
  • 117,907
  • 20
  • 175
  • 238
  • Thank you! I hadn't seen that section. It almost answers my question, but not quite. What is missing is: Does this mean that type names created with typedef share the same namespace as "all other identifiers"? The 4th namespace is described as being used for "ordinary declarators or enumeration constants", but a typedef is neither of those. – Alex D Apr 29 '20 at 15:21
  • 1
    @AlexD Yes, typedef'ed names share the namespace with ordinary identifiers (4th). Updated the answer with a reference. – P.P Apr 29 '20 at 15:30
  • Thank you very much! – Alex D Apr 29 '20 at 15:55
2

Taken from here: https://www.spinellis.gr/cscout/doc/name.html

C has 4 different namespaces. These are not the namespaces from C++, which are accessed by using the keyword namespace. Rather, these are seperate areas for symbols:

  • Tags for a struct/union/enum

  • Members of struct/union (actually a separate namespace is assigned to each struct/union)

  • Labels

  • Ordinary identifiers (termed objects in the C standard)

MrBens
  • 1,227
  • 1
  • 9
  • 19