Lessons to learn from C January 30, 2017 on Drew DeVault's blog

C is my favorite language, though I acknowledge that it has its warts. I’ve tried looking at languages people hope will replace C (Rust, Go, etc), and though they’ve improved on some things they won’t be supplanting C in my life any time soon. I’ll share with you what makes C a great language to me. Take some of these things as inspiration for the next C replacement you write.

First of all, it’s important to note that I’m talking about the language, not its standard library. The C standard library isn’t awful, but it certainly leaves a lot to be desired. I also want to place a few limitations on the kind of C we’re talking about - you can write bad code in any language, and C is no different. For the purpose of argument, let’s assume the following:

I hold myself to these guidelines when writing C, and it is from this basis that I compare other languages with C. It’s not useful to compare bad C to another language, because I wouldn’t want to write bad C either.

Much of what I like about C boils down to this: C is simple. The ultimate goal of any system should be to attain the simplest solution for the problems it faces. C prefers to be conservative with new features. The lifetime of a feature in Rust, for example, from proposal to shipping is generally 0 to 6 months. The same process in C can take up to 10 years. C is a venerable language, and has already long since finished adding core features. It is stable, simple, and reliable.

To this end, language features map closely to behaviors common to most CPUs. C strikes a nearly perfect balance of usability versus simplicity, which results in a small set of features that are easy to reason about. A C expert could roughly predict the assembly code produced by their compiler (assuming -O0) for any given C function. It follows that C compilers are easy to write and reason about.

The same person would also be able to give you a rough idea of the performance characteristics of that function, pointing out things like cache misses and memory accesses that are draining on speed, or giving you a precise understanding of how the function handles memory. If I look at a function in other languages, it’s much more difficult to discern these things with any degree of precision without actually compiling the code and looking at the output.

The compiler also integrates very comfortably with the other tools near it, like the assembler and linker. Symbols in C map 1:1 to symbols in the object files, which means linking objects together is simple and easily reasoned about. It also makes interop with other languages and tools straightforward - there’s a reason every language has a means of writing C bindings, but not generally C++ bindings. The use of headers to declare external symbols and types is also nicer than some would have you believe, since it gives you an opportunity to organize and document your API.

C is also the most portable programming language in the world. Every operating system on every architecture has a C compiler, and they weren’t really considered a viable platform until it did. Once you have a C compiler you generally have everything else, because everything else was either written in C or was written in a language that was implemented in C. I can write C programs on/for Linux, Windows, BSD, Minix, plan9, and a dozen other niche operating systems, or even no operating system, on pretty much any CPU architecture I want. No other language supports nearly as many platforms as C does.

With these benefits acknowledged, there are some things C could do better. The standard library is one of them, but we can talk about that some other time. Another is generics; using void* all the time isn’t good. Some features from other languages would be nice - I would take something similar to Rust’s match keyword. Of course, the fragility of memory management in C is a concern that other languages are wise to address. Undefined behavior is awful.

Even for all of these warts, however, the basic simplicity and elegance of C keeps me there. I would love to see a language that fixes these problems without trying to be the kitchen sink, too.

In short, I like C because C is simple.

Have a comment on one of my posts? Start a discussion in my public inbox by sending an email to ~sircmpwn/public-inbox@lists.sr.ht [mailing list etiquette]

Articles from blogs I read Generated by openring

Command PATH security in Go

Today’s Go security release fixes an issue involving PATH lookups in untrusted directories that can lead to remote execution during the go get command. We expect people to have questions about what exactly this means and whether they might h…

via The Go Programming Language Blog January 19, 2021

Status update, January 2021

Hi all! This month again, my main focus has been wlroots. I’ve focused on the internal renderer refactoring (the so-called “renderer v6"). A lot of the work has now been completed, and all backends now use the new interfaces under-the-hood. With the help …

via emersion January 18, 2021

What's cooking on Sourcehut? January 2021

Another year begins, and hopefully with better prospects for us all. SourceHut has emerged from 2020 relatively unscathed, thankfully, and I hope the same is true of most of our users. A body which, by the way, today numbers 19,647 strong, up 623 from Decemb…

via Blogs on Sourcehut January 15, 2021