Features of C that
seem to have evolved with the compiler-writer in mind are:
I doubt that this was the primary reason for any of those features,
though it was (and certainly should have been) one of the issues taken
into consideration.
Arrays start at 0 rather than 1
Having spent most of my life using C, index-0 feels more natural, but
that's only to be expected.. I've translated a fair amount of index-1
code written for Fortran into index-0 code for C. The translation
process itself can be annoyingly tricky, but properly done, the
translation is pretty much a wash; overall the code is generally about
equally complicated before and after the conversion. However, to the
extent that I saw a difference, I generally found that it was in C's
favor: there were slightly more "+1"s in the Fortran code than in the C
code.
The fundamental C types map directly onto underlying hardware
That can be true, and was particularly true on the platforms where C was
first developed, but the mapping is not necessarily simple or obvious.
Implementations have a lot of freedom in those choices, and developers
have occasionally been surprised by the choices that were made.
However, to the extent that it is true, that was done at least as much
for the benefit of the developer as for the compiler-writer.
The auto keyword is apparently useless
'auto' did not become useless until 'implicit int' was removed from the
language in C99. However, taking advantage of 'implicit int' was never a
very good idea (which is why it was removed from the language), so
'auto' was relatively useless even in C89. To understand why it was
there, you need to look at the history of the languages that were
predecessors to C, where 'auto' was more useful. I don't remember the
details - but they have been mentioned by others in this newsgroup.
Array names in expressions "decay" into pointers
More precisely, that applies to all lvalues of array type, whether or
not they happen to be the names of arrays.
You can't meaningfully talk about the consequences of changing just that
one rule, because it's too tightly integrated into the other rules of C
as they're currently written. For instance, subscripting is only
defined for pointers. The only reason why array[2] refers to the third
element of "array" is because "array" itself automatically converts into
a pointer to the first element of "array". A suggestion that this rule
should not have been chosen must be accompanied with suggestions about
how the other rules of C should have been changed to work properly
without that rule.
However, one relevant issue is that C was designed to rely upon
pass-by-value, which means that an array could only be passed to a
function by creating a pointer. Having that pointer created
automatically was designed as a convenience for the developer, I suspect
that it might actually make things a little more complicated for the
compiler writer, because it means that arrays are treated differently
from other object types.
Floating-point expressions were expanded to double-length-precision everywhere
I suspect that decision was based upon a lot of experience showing that
single-precision was often insufficiently accurate.
In modern C, it's a bit easier to avoid such implicit conversions than
in was in K&R C. In C89, function prototypes were added, which allow you
to declare function arguments to be float, thereby avoiding that
implicit conversion. In C99, almost every <math.h> function that takes a
double argument has another version with the same name plus an 'f' at
the end which takes float arguments and (where appropriate) returns a
float value.