<p>In C, if you declare a <code>struct</code> like:</p>
<pre class="lang-c prettyprint-override"><code>struct point {
    int x, y;
};
</code></pre>
<p>you also have to use <code>struct</code> when referring to <code>point</code>, e.g.:</p>
<pre class="lang-c prettyprint-override"><code>struct point p;  // declare p as struct point
</code></pre>
<p>because all <code>struct</code>, <code>union</code>, and <code>enum</code> names are in a distinct &quot;tags&quot; namespace.  Yes, I know you can use a <code>typedef</code> to import a <code>struct</code>'s tag name into the current scope:</p>
<pre class="lang-c prettyprint-override"><code>typedef struct point point;
point p;         // don't need &quot;struct&quot; now
</code></pre>
<p>Clearly, a tags namespace isn't <em>needed</em> since C++ effectively auto-<code>typedef</code>s <code>struct</code> (and <code>class</code>) declarations.</p>
<p>My question is: does anybody know what Ritchie's rationale for using a separate tags namespace was?  Why weren't <code>struct</code> names just put directly into the current scope so a <code>typedef</code> would be unnecessary?</p>
<p>His <a href="https://www.bell-labs.com/usr/dmr/www/chist.html" rel="noreferrer">The Development of the C Language</a> mentions structures, but nothing about the tags namespace.</p>
<p>Note that I’m really looking for a definitive answer, not speculation.</p>
<p>The only <em>minor</em> benefit is that you can have a <code>struct</code> and variable with the same name, e.g.:</p>
<pre class="lang-c prettyprint-override"><code>struct stat stat;
</code></pre>
<p>To me, however, that's outweighed by ordinarily having to use <code>struct</code> all over the place if you don't use <code>typedef</code>.</p>
<p>For self-referential structures, you don't need the <code>struct</code> prefix either since in C++ you could do:</p>
<pre class="lang-cpp prettyprint-override"><code>struct link;     // forward declare link
struct link {
    void *data;
    link *next;
};
</code></pre>
<p>That works just fine.</p>
<hr />
<p>Note that I'm <em>not</em> asking about why a lot of Unix <code>struct</code> members have prefixes, e.g., <code>sin_family</code>, <code>sin_port</code>, <code>sin_addr</code>. Aside from already knowing the <a href="https://dev.to/pauljlucas/why-many-unix-structs-have-prefixes-48me" rel="noreferrer">answer</a> to that question, it's unrelated since that's about <code>struct</code> <em>members</em> whereas I'm currently asking about <code>struct</code> <em>names</em> in the tags namespace.</p>
<p>FYI: I've been programming in C on-and-off since the 1980s, so I know C. But I've never seen any explanation of Ritchie's rationale for the tags namespace.</p>
<hr />
<p>I originally asked this question <a href="https://retrocomputing.stackexchange.com/questions/30748/rationale-for-requiring-struct-prefix-in-c">here</a> at <a href="https://retrocomputing.stackexchange.com/">Retrocomputing</a>, but it was <a href="https://retrocomputing.stackexchange.com/questions/30748/rationale-for-requiring-struct-prefix-in-c#comment110230_30748">suggested</a> by <a href="https://retrocomputing.stackexchange.com/users/6659/raffzahn">Raffzahn</a> and <a href="https://retrocomputing.stackexchange.com/questions/30748/rationale-for-requiring-struct-prefix-in-c#comment110231_30748">agreed</a> to by <a href="https://retrocomputing.stackexchange.com/questions/30748/rationale-for-requiring-struct-prefix-in-c#comment110231_30748">Adam Hyland</a> that I ask this question here on Langdev.</p>

<language-design><c><history><rationale>
Rationale for requiring struct prefix in C
CC BY-SA 4.0
2024-10-13T07:06:51.127Z
I don't know the answer to your question -- which I have idly wondered myself before. But I like your idea that it might be a solution to what in the C# spec we called the "Color Color" problem: you have a type named Color and you naturally want a property also named Color of that type. The C# name ambiguity rules were carefully designed to allow that; maybe there's some reason why in K&R C that was tricky?
Eric Lippert
CC BY-SA 4.0
2024-10-13T09:40:41.703Z
You don't even need to forward-declare `link` in C++ to be able to use it self-referentially.
G. Sliepen
CC BY-SA 4.0
2024-10-13T12:39:44.457Z
@EricLippert I'm unfamiliar with C# rules to comment. Still, Pascal (a contemporary of C) is able to parse types without a keyword. Pre-ANSI C didn't even have function prototypes (but Pascal did). So was Ritchie just bad at writing parsers?
Paul J. Lucas
CC BY-SA 4.0
2024-10-13T15:10:41.930Z
@EricLippert, also known as the "type-token distinction" in wider discourse: https://en.m.wikipedia.org/wiki/Type%E2%80%93token_distinction
Steve
CC BY-SA 4.0
2024-10-14T19:28:25.263Z
@PaulJ.Lucas: Constructs in Pascal that use an already-declared type name precede it by a colon or the keyword `of`, followed by zero or more carets, and nothing other than a type name could appear in the places a type name could appear.
supercat
CC BY-SA 4.0
2024-10-14T21:36:16.637Z
I don't think there's a definitive answer to be had anymore.  None of the people involved are with us any longer, I don't believe, and to my knowledge, none of the records and documentation of the early development of C provide an explicit rationale for this detail.  I think we can make some very good educated guesses, but that's as much as we can do.
John Bollinger
CC BY-SA 4.0
2024-10-15T01:38:52.440Z
@JohnBollinger Well, Kernighan is still alive. If I can manage to ask him, I will.
Paul J. Lucas
CC BY-SA 4.0
2024-10-15T19:46:46.270Z
@JohnBollinger: The existence of the 1974 C Reference Manual that documents an earlier version of the language requiring that the stem of all types start with a reserved word should be recognized as supplying a clear answer to the question.
supercat
CC BY-SA 4.0
2024-10-15T19:51:02.990Z
Without a `struct` keyword, how would one distinguish whether a block that starts with `{x*y;` declares `y` as a pointer to a structure of some type `x` that might be defined later in the block, or indicates that a compiler should multiply `x` by `y` and discard the result?  Both meanings could be valid if `x` and `y` are defined in an outer scope.
supercat
CC BY-SA 4.0
2024-10-15T20:20:31.907Z
@Bergi: If some uses of a structure name would need a keyword attached, using the same keyword consistently is simpler than having a rule that sometimes requires a keyword and sometimes doesn't.
supercat
CC BY-SA 4.0
2024-10-15T20:50:52.890Z
@supercat That depends on whether you consider the `struct` keyword to be part of the name or part of the declaration.
Bergi
CC BY-SA 4.0
2024-10-15T20:53:56.617Z
@Bergi: A declaration of an object named `p` that points to an `int` would be `int *p;`.  How would one declare an object named `q` that points to a structure with a tag of `foo`, in a manner that's agnostic as to whether such a structure has yet been declared?  If code never tries to use an lvalue of that structure type, a "C74" implementation would have no need to *care* about whether it had been defined or not.
supercat
CC BY-SA 4.0
2024-10-15T21:58:18.793Z
@supercat, I was not aware of the existence of such a manual.  Is there a version available electronically?  I would love to read it.  Either way, however, pre-`typedef` documentation of the requirement for use of the `struct` keyword does not constitute a rationale for that requirement, which is what the question asks for.  Perhaps the manual you describe contains such a rationale, though.
John Bollinger
CC BY-SA 4.0
2024-10-15T22:36:04.003Z
@JohnBollinger: A nice searchable version is at https://www.bell-labs.com/usr/dmr/www/cman.pdf and while it doesn't expressly specify a rationale, the fact that having every type start with a reserved word makes the language easier to parse could not plausibly have gone unnoticed.
supercat
CC BY-SA 4.0
2024-10-15T22:58:26.137Z
@supercat Ah I get you now, I was thrown off by "*a block that starts with `{`…*". You weren't talking about `struct {x* y; …` vs `{x* y; …`, but rather about `struct x* y;` vs `x* y;`.
Bergi
<p>The reason one might use tags is the same as why one would use <code>$sigils</code>. It makes parsing a whole lot easier if you can differentiate the identifiers during the parsing step rather than need semantic knowledge to do so.</p>
<p>Typedefs feel like a later addition to the language. Which then caused issues regarding parsing because now a type isn't always marked by a keyword and an identifier might now be a variable or a type.</p>
<p>The only symbols that need to be exported from the compiled translation unit being sent to the linking step are global variables and functions (which could be considered special kind of global).</p>
<p>Putting everything else into a tagged namespace prevents pollution of that inter-translation unit namespace with type names.</p>

CC BY-SA 4.0
2024-10-13T09:20:52.557Z
2024-10-13T10:01:18.587Z
2024-10-13T10:01:18.587Z
ratchet freak
CC BY-SA 4.0
2024-10-13T12:28:03.213Z
Do you have any evidence that `typedef` came later?
Paul J. Lucas
CC BY-SA 4.0
2024-10-13T15:41:05.757Z
@PaulJ.Lucas [the C compiler in V6 Unix](https://github.com/dspinellis/unix-history-repo/tree/Research-V6/usr/source/c) doesn’t support `typedef`, whereas [the V7 compiler](https://github.com/dspinellis/unix-history-repo/tree/Research-V7/usr/src/cmd/c) does. So `typedef` was introduced sometime between 1975 and 1979 (or 1978 when the first K&R C book was published).
Stephen Kitt
CC BY-SA 4.0
2024-10-13T22:14:13.213Z
@StephenKitt Huh. The lack of `typedef` in embryonic C does make making all type declarations start with a keyword a stronger argument. I tried poking around in the git logs, but it's pretty sparse — no smoking gun like "Added typedef to simplify declarations."
Paul J. Lucas
CC BY-SA 4.0
2024-10-13T22:29:32.957Z
@StephenKitt I just found [this](https://www.bell-labs.com/usr/dmr/www/cman.pdf) that documents C for 6th Ed. Unix — no `typedef`.
Paul J. Lucas
CC BY-SA 4.0
2024-10-14T16:44:33.023Z
@PaulJ.Lucas what git logs exist for really old changes?  C is a *lot* older than git.
Mark Ransom
CC BY-SA 4.0
2024-10-14T19:15:07.533Z
@MarkRansom The fact that C is older than git doesn't matter. If Ritchie were using SCCS, there are ways of migrating an SCCS repo complete with all its changes and commit comments to git (assuming such a repo actually ever existed and somebody took the time to do such a migration).
Paul J. Lucas
CC BY-SA 4.0
2024-10-14T19:25:37.340Z
@PaulJ.Lucas my question was legitimate, what logs are there for old changes?  The mechanics of how they came to exist are irrelevant, except for the implications of completeness.  It would be interesting to know if *any* source control was used for the early versions.
Mark Ransom
CC BY-SA 4.0
2024-10-14T23:07:33.737Z
@MarkRansom I don't know what VCS logs, if any, exist.
Paul J. Lucas
CC BY-SA 4.0
2024-10-15T00:15:57.393Z
@PaulJ.Lucas I think what Mark wants to know is, when you said *"I tried poking around in the git logs"*, which logs were you looking in and where can they be found?
kaya3
CC BY-SA 4.0
2024-10-15T01:36:51.750Z
@kaya3 See Stephen Kitt's [comment](https://langdev.stackexchange.com/questions/4105/rationale-for-requiring-struct-prefix-in-c/4106?noredirect=1#comment13436_4106) above.
Paul J. Lucas
CC BY-SA 4.0
2024-10-15T16:12:21.623Z
@PaulJ.Lucas the unix-history-repo [is mostly a nice way of exploring the history of Unix and BSD](https://github.com/dspinellis/unix-history-repo/); it includes partial SCCS and CSV histories but they don’t cover much. Most of the git repository is just reconstructed from snapshots.
Stephen Kitt
<blockquote>
<p>Why weren't <code>struct</code> names just put directly into the current scope so a <code>typedef</code> would be unnecessary?</p>
</blockquote>
<p><code>typedef</code> <em>is</em> unnecessary.  There's nothing that you can express in C with the help of <code>typedef</code> that you cannot also express without.  It does make a few things clearer, but it can also be, and too often is, (mis)used to make things more obscure.</p>
<p>I acknowledge that</p>
<blockquote>
<p>Note that I’m really looking for a definitive answer, not speculation.</p>
</blockquote>
<p>, but I don't think there's a definitive answer available at this point.</p>
<p>Dennis Ritchie has acknowledged Algol 68 as having a significant impact on his design of C's type system, so we know that it was well known to him.  He may even have drawn C's <code>struct</code> and <code>union</code> keywords directly from Algol, which uses the same ones to declare its structure and union types.  Algol 68 has an analog of C's <code>typedef</code> (modes), but no analog of C's tags.  Neither did C's direct ancestors, BCPL and B, have any such feature (they had only a very simple type system, whose shortcomings were the initial inspiration for C), so this seems to have been Ritchie's own invention.</p>
<p>Why introduce tags and the tag namespace when Ritchie's main model for C's type system did things differently?  I see only a few alternatives, none exclusive:</p>
<ul>
<li><p>tags and keywords may have been a convenience, making the compiler easier to write or easier to keep small (remember that executable size was a major consideration in that day).</p>
<ul>
<li>as a special case of this, tags, and especially type-category keywords, might have simplified the initial introduction of structures into the early C language parser.</li>
</ul>
</li>
<li><p>Ritchie may have considered tags and pervasive use of the <code>struct</code> keyword to be a superior design.  It does have the advantage of being clear at the point of a declaration what type category each declared object belongs to, which I personally value today.  I <em>prefer</em> to refer to structure, union, and enum types in my C code using keyword / tag syntax.</p>
</li>
</ul>
<p>I'd be inclined to lean in the pragmatism direction.</p>

CC BY-SA 4.0
2024-10-14T22:50:00.883Z
2024-10-14T22:50:00.883Z
John Bollinger
CC BY-SA 4.0
2024-10-14T23:13:45.543Z
When I said "... so a `typedef` would be unnecessary," I meant, "... so a `typedef` would be unnecessary **for making using structure types not require the use of the `struct` prefix**."
Paul J. Lucas
# Rationale for requiring struct prefix in C
Posted by: username_0 on 2024-10-13
In C, if you declare a struct like:
struct point {
    int x, y;
};

you also have to use struct when referring to point, e.g.:
struct point p;  // declare p as struct point

because all struct, union, and enum names are in a distinct "tags" namespace.  Yes, I know you can use a typedef to import a struct's tag name into the current scope:
typedef struct point point;
point p;         // don't need "struct" now

Clearly, a tags namespace isn't needed since C++ effectively auto-typedefs struct (and class) declarations.
My question is: does anybody know what Ritchie's rationale for using a separate tags namespace was?  Why weren't struct names just put directly into the current scope so a typedef would be unnecessary?
His The Development of the C Language mentions structures, but nothing about the tags namespace.
Note that I’m really looking for a definitive answer, not speculation.
The only minor benefit is that you can have a struct and variable with the same name, e.g.:
struct stat stat;

To me, however, that's outweighed by ordinarily having to use struct all over the place if you don't use typedef.
For self-referential structures, you don't need the struct prefix either since in C++ you could do:
struct link;     // forward declare link
struct link {
    void *data;
    link *next;
};

That works just fine.

Note that I'm not asking about why a lot of Unix struct members have prefixes, e.g., sin_family, sin_port, sin_addr. Aside from already knowing the answer to that question, it's unrelated since that's about struct members whereas I'm currently asking about struct names in the tags namespace.
FYI: I've been programming in C on-and-off since the 1980s, so I know C. But I've never seen any explanation of Ritchie's rationale for the tags namespace.

I originally asked this question here at Retrocomputing, but it was suggested by Raffzahn and agreed to by Adam Hyland that I ask this question here on Langdev.
**Tags:** language-design c history rationale
> **Comments:**
> **username_1**: I don't know the answer to your question -- which I have idly wondered myself before. But I like your idea that it might be a solution to what in the C# spec we called the "Color Color" problem: you have a type named Color and you naturally want a property also named Color of that type. The C# name ambiguity rules were carefully designed to allow that; maybe there's some reason why in K&R C that was tricky?  
> **username_2**: You don't even need to forward-declare `link` in C++ to be able to use it self-referentially.  
> **username_0**: @EricLippert I'm unfamiliar with C# rules to comment. Still, Pascal (a contemporary of C) is able to parse types without a keyword. Pre-ANSI C didn't even have function prototypes (but Pascal did). So was Ritchie just bad at writing parsers?  
> **username_3**: @EricLippert, also known as the "type-token distinction" in wider discourse: https://en.m.wikipedia.org/wiki/Type%E2%80%93token_distinction  
> **username_4**: @PaulJ.Lucas: Constructs in Pascal that use an already-declared type name precede it by a colon or the keyword `of`, followed by zero or more carets, and nothing other than a type name could appear in the places a type name could appear.  
> **username_5**: I don't think there's a definitive answer to be had anymore.  None of the people involved are with us any longer, I don't believe, and to my knowledge, none of the records and documentation of the early development of C provide an explicit rationale for this detail.  I think we can make some very good educated guesses, but that's as much as we can do.  
> **username_0**: @JohnBollinger Well, Kernighan is still alive. If I can manage to ask him, I will.  
> **username_4**: @JohnBollinger: The existence of the 1974 C Reference Manual that documents an earlier version of the language requiring that the stem of all types start with a reserved word should be recognized as supplying a clear answer to the question.  
> **username_4**: Without a `struct` keyword, how would one distinguish whether a block that starts with `{x*y;` declares `y` as a pointer to a structure of some type `x` that might be defined later in the block, or indicates that a compiler should multiply `x` by `y` and discard the result?  Both meanings could be valid if `x` and `y` are defined in an outer scope.  
> **username_4**: @Bergi: If some uses of a structure name would need a keyword attached, using the same keyword consistently is simpler than having a rule that sometimes requires a keyword and sometimes doesn't.  
> **username_6**: @supercat That depends on whether you consider the `struct` keyword to be part of the name or part of the declaration.  
> **username_4**: @Bergi: A declaration of an object named `p` that points to an `int` would be `int *p;`.  How would one declare an object named `q` that points to a structure with a tag of `foo`, in a manner that's agnostic as to whether such a structure has yet been declared?  If code never tries to use an lvalue of that structure type, a "C74" implementation would have no need to *care* about whether it had been defined or not.  
> **username_5**: @supercat, I was not aware of the existence of such a manual.  Is there a version available electronically?  I would love to read it.  Either way, however, pre-`typedef` documentation of the requirement for use of the `struct` keyword does not constitute a rationale for that requirement, which is what the question asks for.  Perhaps the manual you describe contains such a rationale, though.  
> **username_4**: @JohnBollinger: A nice searchable version is at https://www.bell-labs.com/usr/dmr/www/cman.pdf and while it doesn't expressly specify a rationale, the fact that having every type start with a reserved word makes the language easier to parse could not plausibly have gone unnoticed.  
> **username_6**: @supercat Ah I get you now, I was thrown off by "*a block that starts with `{`…*". You weren't talking about `struct {x* y; …` vs `{x* y; …`, but rather about `struct x* y;` vs `x* y;`.  
---
## 2 answers
### Answer by username_7 on 2024-10-13. Score: 19
The reason one might use tags is the same as why one would use `$sigils`. It makes parsing a whole lot easier if you can differentiate the identifiers during the parsing step rather than need semantic knowledge to do so.

Typedefs feel like a later addition to the language. Which then caused issues regarding parsing because now a type isn't always marked by a keyword and an identifier might now be a variable or a type.

The only symbols that need to be exported from the compiled translation unit being sent to the linking step are global variables and functions (which could be considered special kind of global).

Putting everything else into a tagged namespace prevents pollution of that inter-translation unit namespace with type names.
> **Comments:**
> **username_0** (2024-10-13): Do you have any evidence that `typedef` came later?  
> **username_8** (2024-10-13): @PaulJ.Lucas [the C compiler in V6 Unix](https://github.com/dspinellis/unix-history-repo/tree/Research-V6/usr/source/c) doesn’t support `typedef`, whereas [the V7 compiler](https://github.com/dspinellis/unix-history-repo/tree/Research-V7/usr/src/cmd/c) does. So `typedef` was introduced sometime between 1975 and 1979 (or 1978 when the first K&R C book was published).  
> **username_0** (2024-10-13): @StephenKitt Huh. The lack of `typedef` in embryonic C does make making all type declarations start with a keyword a stronger argument. I tried poking around in the git logs, but it's pretty sparse — no smoking gun like "Added typedef to simplify declarations."  
> **username_0** (2024-10-13): @StephenKitt I just found [this](https://www.bell-labs.com/usr/dmr/www/cman.pdf) that documents C for 6th Ed. Unix — no `typedef`.  
> **username_9** (2024-10-14): @PaulJ.Lucas what git logs exist for really old changes?  C is a *lot* older than git.  
> **username_0** (2024-10-14): @MarkRansom The fact that C is older than git doesn't matter. If Ritchie were using SCCS, there are ways of migrating an SCCS repo complete with all its changes and commit comments to git (assuming such a repo actually ever existed and somebody took the time to do such a migration).  
> **username_9** (2024-10-14): @PaulJ.Lucas my question was legitimate, what logs are there for old changes?  The mechanics of how they came to exist are irrelevant, except for the implications of completeness.  It would be interesting to know if *any* source control was used for the early versions.  
> **username_0** (2024-10-14): @MarkRansom I don't know what VCS logs, if any, exist.  
> **username_10** (2024-10-15): @PaulJ.Lucas I think what Mark wants to know is, when you said *"I tried poking around in the git logs"*, which logs were you looking in and where can they be found?  
> **username_0** (2024-10-15): @kaya3 See Stephen Kitt's [comment](https://langdev.stackexchange.com/questions/4105/rationale-for-requiring-struct-prefix-in-c/4106?noredirect=1#comment13436_4106) above.  
> **username_8** (2024-10-15): @PaulJ.Lucas the unix-history-repo [is mostly a nice way of exploring the history of Unix and BSD](https://github.com/dspinellis/unix-history-repo/); it includes partial SCCS and CSV histories but they don’t cover much. Most of the git repository is just reconstructed from snapshots.  
---
### Answer by username_5 on 2024-10-14. Score: 2
> Why weren't `struct` names just put directly into the current scope so a `typedef` would be unnecessary?

`typedef` *is* unnecessary. There's nothing that you can express in C with the help of `typedef` that you cannot also express without. It does make a few things clearer, but it can also be, and too often is, (mis)used to make things more obscure.

I acknowledge that

> Note that I’m really looking for a definitive answer, not speculation.

, but I don't think there's a definitive answer available at this point.

Dennis Ritchie has acknowledged Algol 68 as having a significant impact on his design of C's type system, so we know that it was well known to him. He may even have drawn C's `struct` and `union` keywords directly from Algol, which uses the same ones to declare its structure and union types. Algol 68 has an analog of C's `typedef` (modes), but no analog of C's tags. Neither did C's direct ancestors, BCPL and B, have any such feature (they had only a very simple type system, whose shortcomings were the initial inspiration for C), so this seems to have been Ritchie's own invention.

Why introduce tags and the tag namespace when Ritchie's main model for C's type system did things differently? I see only a few alternatives, none exclusive:

* tags and keywords may have been a convenience, making the compiler easier to write or easier to keep small (remember that executable size was a major consideration in that day).

  + as a special case of this, tags, and especially type-category keywords, might have simplified the initial introduction of structures into the early C language parser.
* Ritchie may have considered tags and pervasive use of the `struct` keyword to be a superior design. It does have the advantage of being clear at the point of a declaration what type category each declared object belongs to, which I personally value today. I *prefer* to refer to structure, union, and enum types in my C code using keyword / tag syntax.

I'd be inclined to lean in the pragmatism direction.
> **Comments:**
> **username_0** (2024-10-14): When I said "... so a `typedef` would be unnecessary," I meant, "... so a `typedef` would be unnecessary **for making using structure types not require the use of the `struct` prefix**."  
---
