Hacker News new | ask | show | jobs
by akiarie 29 days ago
C is still, by far, the simplest language that we have.

Although many newer languages are safer (with the exclusion of Rust, primarily by being slower) the same kinds of issues that are there in C are there in these languages, their effects are just harder to see.

People complain about C as though they know how to fix it.

3 comments

C is not a simple language in the sense that writing software in C is simple, and I think that's the only useful way to understand the word "simple" in this context.

Brainfuck is "simple" by any other definition as well, but that's not a useful quality.

C is a far simpler language than, for example, Swift. It's cognitive load in order to actually write something is pretty small - even the authors state that their book about C is intentionally slim because the concepts to understand are not that many.

That doesn't mean the C is a safer language than Swift, or a less-capable language than Swift. But in terms of "easy to understand along the happy-path", it's a lot easier to get going in C.

Swift, for example, bakes a whole load of CS-degree-level ideas and concepts into the basic language with its optionals, unwrapping, type-inference, async/await, existential types, ... ... ... . C doesn't do any of that. There are (many!) more footguns in C, but the language is less complex as a result.

Brainfuck is not at all simple, from that point of view. This is a valid Brainfuck program:

>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]<. >+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[<++++ >-]<+.[-]++++++++++.

This is the equivalent C program

#include <stdio.h> int main() { printf("Hello world!\n"); }

One of these is far simpler than the other.

[edit: changed to make the examples do the same thing]

The point I'm getting at is that your definition of "simple" (a word that should be banned among programmers) is not useful, if it is even meaningful.

The brainfuck example is "simpler": Only 8 kinds of tokens! Not really useful, though.

The cognitive load of _actually delivering software_ written in C is immensely greater than doing so with Swift, or Rust, or Python, or Java, even Zig, despite all of those leveraging much heavier machinery in order to deliver a friendlier abstract model for you to program against.

The tragedy of C is that, in addition only delivering very baseline abstraction tools, it also adds its own set of seemingly arbitrary rules and requirements that come from nowhere but the C standard. Fictitious limitations to suit a bygone era. The abstract model of C is fine in some places, but definitely not fine in other places, and my hypothesis is that most UB in practice comes from a mismatch between programmer intuitions and C's idiosyncracies.

Calling something "simple" to use and learn is a valid use of the word, sorry. Not going to stop doing that.

> The cognitive load of _actually delivering software_ written in C is immensely greater than doing so with Swift, or Rust, or Python, or Java, even Zig, despite all of those leveraging much heavier machinery in order to deliver a friendlier abstract model for you to program against

Sorry, I couldn't disagree more.

I find the simplicity of C to be elegant. You know the rules; it's like the entire C language is the 1-page summary of the encyclopaedia of C++ or Swift or Java, or (insert more-modern language here). The key to working well in C is in defining modular code with well-understood interfaces. I've got 40 years of programming in C so far, and the nightmare stories ran out after the first few years. Programming discipline is a thing.

Similarly, ObjC is a far superior, much simpler, object-oriented language than C++, there's about 15 different things over C, and you know the language. Template metaprogramming. Phooey! You'll still have to learn object-orientated programming semantics, but it's a "simple" language.

BTW: If you think the brainfuck language example is in any way easier to understand than the C one, I think you might need medication. /j

> I've got 40 years of programming in C so far, and the nightmare stories ran out after the first few years.

You need to find something more interesting to do ;)

Oh, I do. I'm building a two-story 1000 sq.ft garage right now - more workshop than garage tbh [1], I've just built a roll-off-roof observatory [2], the currently empty pad behind it is for a radio-telescope, last set up in London [3], still needs to be assembled in the new house. Right now I'm into the fun stuff of automating everything in the observatory. I've also recently taken up archery, and I'm enjoying that. I've written (well Claude has) an optimising compiler for a memory-managing language for the 6502 [4], but I'm just instrumenting (this bit is me) the IR so it can also target the M chip on my Mac. Eventually it'll also target m68k so I can bring up the Atari ST on the FPGA that is currently just emulating the atari 8-bit (I have a 120MHz 6502 at the moment :). The 'x' in 'xt' is from 'atari Xl' and the 't' is from 'atari sT'. The compiler is called 'xtc'. Both will run MiNT and the blitter on the FPGA is designed to integrate well with GEM, the graphics environment on the ST - even the XL version will have a graphical UI running at 1080p :)

So I have a few things to keep me busy right now.

1: http://0x0000ff.co.uk/img/garage/garage-layout.png

2: http://0x0000ff.co.uk/img/observatory/roll-off-roof-observat...

3: http://0x0000ff.co.uk/img/dish/dish.jpg

4: http://atari-xt.com/

another useful sense is easy to understand/read what programmer want to write. (ofc exclude mad code with macros etc).

Brainfuck is absolutely not simple in this case

C sits right in the middle between assembly and BASIC in terms of simplicity. You can't do a simple popcnt, but you can implement jump tables.

It's slower than Fortran and, depending on the platform, cobol. It's a bigger minefield than any language that came after it barring C++.

The only real advantage I can ascribe to C is that it's actually still being used after all these years, and it mostly works similarly on most hardware, like a Java for people who enjoy the casino.

Fixing C without breaking existing C code is pretty much impossible. You can start by defining warnings for UB, but then you will break any of the more trivial examples in the article. You can also start by simply killing off weird platforms (force a specific amount of bits for instance, screw the weird 16 bit char chips). Making casts explicit would probably fix a lot of problems too, though you'd need better syntax for that.

There is no fixing C without changing what C really is.

Can you elaborate what do you think C has in terms of simplicity that Zig doesn't, and which "same kinds of issues" do you think it has?

I'm not an expert in either language but my anecdotal experience disagrees with this - writing Zig has been far simpler and less error-prone than writing C.