This particular quirk is a few years older than C itself, actually! C was based on a similar language called B. Now B was originally written for PDP-7 and similar machines, which could only address words in memory, not individual bytes. So it was designed "typeless" - the only and always-implicit type in that language is the machine word, so e.g. (a+b) always adds two ints, and (*a) always dereferences a pointer. Otherwise, the syntax was very similar to C:
max(a, b) {
if (a > b)
return a;
else
return b;
}
swap(a, b) {
auto c = *a;
*a = *b;
*b = c;
}
main() {
auto a, b;
swap(&a, &b);
}
Since all functions took zero or more words as arguments, and returned a word, there was no need for function prototypes, either, or for function pointer types - if you used () on something, it was treated as a function / function pointer with the corresponding number of parameters. Even labels / goto worked like that.When they got a PDP-11, which had byte-addressed memory, this simplistic approach no longer worked - they had to distinguish char/int and char*/int*. So C added types and pointers - but kept int as the default type, as well as the keyword "auto" (which is completely redundant in C if you specify the type), so that existing B code could be easily ported. For the same reason, they allowed calling functions without declaring them, assuming int as return type.
This is also presumably why pre-ANSI K&R C had that weird syntax for parameter types:
max(a, b)
int a;
int b;
{ ... }
If you omit the types, they all default to ints, and it becomes identical to the B declaration!That implicit int rule made it into the ANSI C89 / ISO C90 standard, since it was still common enough in K&R C code floating around at the time, and they were trying to not break things too much. It eventually got removed in C99, except that "short" and "long" still allow to omit the following "int". The useless "auto" is still around, though, although it might eventually get repurposed the same way it was in C++.
"C is quirky, flawed, and an enormous success."
But sure, I wouldn't recommend anyone choose C as a language for new software unless they have an extremely good reason, or if you really love stuff like implementing every data structure you use from scratch and using void* as a kind of wildly unsafe generic.
Unless you are doing firmware where all those constraints are still around, and you have to deal with whatever compiler the vendor supplies for their microcontroller, which will almost certainly be some variant of C.
But yeah doing so is being a special snowflake, still they are in business to this day.