The design of the C language began, to my understanding, in 1969 at Bell Labs, where Dennis Ritchie was working at the time. The language was based on B, a language which used a single data type that could be interpreted differently in different contexts (somewhat like assembly language). Keeping as close as possible to the structure of B was one of the aims of the language. B looked like this (quoting from wikipedia, which cites the example as being from the User's Reference to B):
/* The following function will print a non-negative number, n, to
the base b, where 2<=b<=10. This routine uses the fact that
in the ASCII character set, the digits 0 to 9 have sequential
code values. */
printn(n, b) {
extrn putchar;
auto a;
if (a = n / b) /* assignment, not test for equality */
printn(a, b); /* recursive */
putchar(n % b + '0');
}
Note that the declarations of a local variable (auto a
) and import of a global symbol (extrn putchar
) both follow the same "kind-of-thing name-of-the-thing" layout that C uses. But in B, the "kind-of-thing" was just a simple choice from a predefined set of keywords, so caused no parsing problems. Extending that to the complex syntax of data types is where the problem came in.
Now, one can imagine that while designing C Ritchie would have noticed that the parsing for types in declarations was becoming more complex than a context-free grammar can handle. Some developers may have been deterred by this fact, and would have accepted the loss of this aspect of similarity to B in favour of a simpler parser design.
It's hard to say exactly why this didn't happen, but it may be because of the culture of Bell Labs, where a large number of extremely talented programmers and computer scientists were congregating at the time. Among them was Alfred Aho, who had recently published his PhD thesis on the subject of Indexed Grammars, and would therefore have been quite familiar with the consequences of leaving the safety of Context-free Grammars and the kinds of techniques that could be used to efficiently parse such languages. (Along with another Bell Labs researcher, Jeffrey Ullman, he would go on to write the best-known book on the subject of compiler design). It's just a hypothesis, as I have no evidence that they ever talked about the subject, but discussing any such troubles with Aho may have given Ritchie the confidence to continue with his design rather than rewriting to a more conservative type of grammar.
std::vector<int> foo();
isn't a variable that's default-initialized, it's a function. In C, because you don't have constructors and all other function calls have an identifier before them, this isn't actually that big of an issue, though.std::initializer_list
rules...typedef
nor qualfiiers. I think a sound argument could be made that when those were added to the language, the syntax for declarations should have been tweaked to allow parsing without the symbol table. The language could have continued to recognizeint x;
as equivalent toint:x
, but requireduserIdentifier*: x;
oruserIdentifier: *x;
rather thanuserIdentifier *x;
, whose meaning would depend upon the definition ofuserIdentifier
.