I spent most of my career writing C code. I’ve also got an old-timey and grumpy outlook so I’m inclined to look on those disparaging C with a certain skepticism. Often, complaints about C are easy to dismiss as the uninformed mewlings from those who neither know nor write in C. But there are also complaints from knowledgeable programmers who have extensive experience in C.
The complaints from those who know what they’re talking about usually center around the issue of the “safety” of C and, in particular, its undefined behaviors. How can you write good code when there are so many undefined behaviors, when there’s no bound checking for arrays, and all the other safety issues? It’s a good question and seems compelling when you see it but, somehow, it always ran counter to my experience. Like every other programmer, I’ve written lots of buggy code but none of it was because of undefined behaviors or because I busted an array bound. To me, the complaints of C being unsafe always seemed more theoretical than practical.
I just came across a 2017 paper, Some Were Meant for C, by Stephen Kell that examines the issue of C’s safety and concludes that (1) the problems with C are not in the language itself but in its typical implementations and (2) that the features of C are essential for systems programming where “systems programming” is defined in a way that includes but is different from, say, kernel implementation.
One of Kell’s major points is that there’s nothing in the C specification that prevents a safe implementation. Rather, he says, it’s the erroneous belief that C users care mostly about performance that keeps compiler writers from adding, for example, bounds checking code. He also has a lot to say about the undefined behaviors and why they’re necessary in a language like C.
It’s a fairly long paper but definitely worth reading if you’re interested in C or confused about all the talk about its not being safe.