Henry Spencer's 10 Commandments for C Programmers
<https://www.seebs.net/c/10com.html>
On Wed, May 27, 2020 at 10:38 AM Ronald Natalie <ron(a)ronnatalie.com> wrote:
The large areas of undefined and unspecified behavior
has always been an
issue in C. It was somewhat acceptable when you were using it as a direct
replacement for assembler,
but Java and many of other follow-ons endevaored to be more
portable/rigourous. Of course, you can write crap code in any language.
It didn’t take modern C to do this. On the PDP-11 (at least not in split
I/D mode), location zero for example contained a few assembler instructions
(p&P6) which you could print out.
Split I/D and VAX implementations made this even worse by putting a 0 at
location 0. When we moved from the VAX to other processors we had
location zero unmapped. For the
first time, accessing a null pointer ended up trapping rather than either
resulting in a null (or some random data). Eventually, we added a
feature to the kernel called “Braindamanged
Vax compatibility Mode” that restored the zero to location zero. This
was enabled by a field we could poke into the a.out header because this was
needed on things we didn’t have
source code to (things we did we just fixed).
Similar nonsense we found where the order that function args are evaluated
was relied upon. The PDP-11, etc… evaluated them right-to-left because
that’s how they had to push them
on the stack for the call linkage. We had one machine that did that in
the opposite order (I considered flipping the compiler behavior anyhow0 and
when we got to the RISC architectures,
things were passed in registered so the evaluation was less predictable.
I already detailed the unportability problem I found where the BSD kernel
“converted by union”.
The most amusing thing I’d have to say was that one day I got a knock on
my office door. One of the sales guys from our sister company wanted to
know if I could write some Novell
drivers for an encrypting ethernet card they were selling. The
documentation for writing the driver was quite detailed but all describing
i386 assembler interfaces (and the examples
were in assembler). About a week into the project I came to realization
that the linkages were all the C subroutine calls for that platform. The
caller was C and there was no particular
reason why the driver wasn’t also written in C.