6

In C, most of the code declaring structs will follow this pattern:

/* struct forward-declaration */
typedef struct T T ;

/* struct definition */
typedef struct T
{
   /* etc. */
} T ;

This is so prevalent most developers I talked with didn't even know the code above did two things at the same time (struct declaration, then aliasing the struct name in the normal namespace), and just wrote it out of habit.

In C++, the issue is mitigated so you can omit the typedefing part. In C# and in Java, the designers didn't even bother. So those languages won't help understand why C does this that way.

So, after Oliver Charlesworth's suggestion:

Is there a technical reason to have struct T in a separate namespace from other normal identifiers?

Edit

The relevant section in the C89/C90 standard is:

6.1.2.3 Name spaces of identifiers

It 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 tags of structure, unions and enumerations (disambiguated by following any of the keywords struct, union, or enum).

  • [...]

  • all other identifiers. called ordinary identifiers (declared in ordinary declarators or as enumeration constants).

The text for C11 (n1570:6.2.3 standard draft) is more or less the same.

Community
  • 1
  • 1
paercebal
  • 81,378
  • 38
  • 130
  • 159
  • Isn't this for typedefs rather than for structs? IOW, what does the `typedef` change? – Jongware Nov 30 '14 at 11:39
  • 2
    Not 100% clear what you're asking here; is it "why is `struct T` in a separate namespace from `T`"? – Oliver Charlesworth Nov 30 '14 at 11:43
  • [Hysterical reasons](http://www.catb.org/jargon/html/H/hysterical-reasons.html). Basically, compilers were small and not very smart back when. – n. m. could be an AI Nov 30 '14 at 12:47
  • @OliverCharlesworth : You're absolutely right. I updated my question to make it clearer, shamelessly copy-pasting your suggestion. Thanks!.. :-) – paercebal Nov 30 '14 at 13:22
  • @Jongware : Try writing C code without the typedef style above, and you'll see in your code, everywhere T is mentioned, it will be qualified with the keyword struct, which can be a bit of a pain. I've never understood the reason. – paercebal Nov 30 '14 at 13:24
  • 1
    Goes back to *very* early C, back when even the [struct members](http://stackoverflow.com/a/4970260/17034) where in the global namespace. They overshot the fix a bit, perhaps. – Hans Passant Nov 30 '14 at 14:09
  • @HansPassant : You should add a full answer on that subject with a bit more information (copy/pasted/adjusted from your other answer, and/or other tidbits)... Because that would be a satisfactory answer for this question, I believe. Is there a document describing this pre-historical C? (e.g., for C++: https://isocpp.org/blog/2014/10/from-the-archives-c-as-close-as-possible-to-c-but-no-closer-a.-koenig-and-b ) – paercebal Nov 30 '14 at 14:35
  • The [C99 rationale](http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf) (6.2.3) says, there had been a lot of variation in implementations. (Which makes sense to me, a separate namespace cannot break existing code relying on either choice, apart from relying on a compiler error.) The same reasoning, however, would apply for having separate namespaces for structure and union tags, so this is not the whole story. Some details about this historic variation would be helpful. – mafso Nov 30 '14 at 21:24
  • @paercebal: I think Hans' reasoning is off-topic here (though nonetheless interesting), as this is about the separate name space for tags, not for members. For a document: I don't know of a freely available publication of the first version of K&R TCPL. And I doubt that would be helpful here; variation in implementations may indicate that K&R was vague on this. – mafso Nov 30 '14 at 21:32
  • 1
    possible duplicate of [What is the rationale behind typedef vs struct/union/enum, couldn't there be only one namespace?](http://stackoverflow.com/questions/3897302/what-is-the-rationale-behind-typedef-vs-struct-union-enum-couldnt-there-be-onl) – Joseph Quinsey Dec 05 '14 at 01:38
  • @JosephQuinsey : I agree. I'll vote for closing the question for being a duplicate. Thanks. – paercebal Dec 06 '14 at 07:52
  • That possible duplicate doesn't really ask for separate namespaces, but why structures aren't automatically typedefed. If there was only one namespace, they still weren't, but typedefing them to the structure tag (as in `typedef struct foo foo;`) would be simply illegal (as `foo` is redefined in the same scope). – mafso Dec 08 '14 at 00:08

2 Answers2

2

Until typedef was added to complicate parsing, object declarations would always start with a reserved word: struct, int, char, float, or double, and maybe long or union (not sure whether those were added before or after typedef). Since structure tags couldn't appear anywhere except after the keyword struct, there was no reason for a compiler to care if a structure tag shared a name with any other identifier.

The need to have typedef names be distinct from those of any other identifiers is a result of grammatical ambiguity created by allowing custom types to be used in object declarations or cast expressions without any reserved words or punctuators (at the start of a function, x * y; could either create an object named y of type x*, or could multiply x by y and discard the result, and (x)(y) could either cast y to type x or invoke function x with argument y).

supercat
  • 77,689
  • 9
  • 166
  • 211
0

The first line is only needed if you want to reference struct T using the name T inside the second declaration.

For structs that don't contain such references, only the second form is needed. For such cases, for simplicity and brevity, I would recommend dropping the then pointless struct tag:

typedef struct {
  /* interesting fields go here */
} T;

Also, the typedef doesn't "bring the struct name into the normal namepace", it creates (like typedef always does) an alias (T) for a different type name struct T. Of course there is no connection between the spelling of names here, which is why I recommend dropping tagging the struct in the first place, it just adds a name that is pointless most of the time.

paercebal
  • 81,378
  • 38
  • 130
  • 159
unwind
  • 391,730
  • 64
  • 469
  • 606
  • 1
    Thanks for the answer but... It doesn't answer my question, which was: was there a technical reason to separate the struct types namespace from the from the normal (function and variables) namespace. (See C89/C90 standard, 6.1.2.3 Name spaces of identifiers) – paercebal Nov 30 '14 at 13:31
  • Another advantage of the `struct tagname` form is that one can have a header file define pointers, function parameters, and function return types of such structures without having to worry about whether a complete struct type definition is in scope. If some users of a header would use an `importWidget` function that expects an argument of type `struct Widget*`, but others won't, and identifies the type as `struct tagName*` in that prototype, client code that doesn't use the type won't need to include a definition for it. – supercat Apr 27 '21 at 20:45