Live data from Hacker News

Why I Always End Up Going Back to C

deplet.ing

31–40 of 76 posts

Re: Why I Always End Up Going Back to C

#31
post #7

> The language shows you the machine, a machine which is not forgiving to mistakes. Assembly does that, C not really, it is a myth that it does.

I'm being pedantic, but on modern hardware, the ISA is an abstraction over microarchitecture and microcode. It's no longer a 1-to-1 representation of hardware execution. But, as programmers, it's as low as we can go, so the distinction is academic.

Re: Why I Always End Up Going Back to C

#32
post #29
post #5

Earlier quoted context omitted.

> You build stuff, and there is so many manual steps "The real goal isn’t to write C once for a one-off project. It’s to write it for decades. To build up a personal ecosystem of practices, libraries, conventions, and tooling that compound over time."

You mean, you are not worried about high complexity of codebase because you work with it every day for decades, so you know all this complexity by heart? This basically requires one to be working solo, neither receiving not sharing the source code with others, treating third-party libraries as blackboxes. I guess this can work for some people, but I don't think it would work for everyone.

> so you know all this complexity by heart?

No. It's that you've built up a personal database of libraries, best-practices, idioms, et al. over decades.

When you move on to a new project, this personal database comes with you. You don't need to wonder if version X of Y framework or library has suddenly changed and then spend a ton of time studying its differences.

Of course, the response to this is: "You can do this in any language!"

And you'd be right, but after 20 years straight of working in C alongside teams working in Java, Perl, Python, Scheme, OCaml, and more, I've only ever seen experienced C programmers hold on to this kind of digital scrapbook.

Re: Why I Always End Up Going Back to C

#33
I wound up going back to C in a big way about five years ago when I embarked on Scheme for Max, an extension to Max/MSP that lets you use s7 Scheme in the Max environment. Max has a C SDK, and s7 is written in 100% ANSI C. (Max also has C++ SKD, but is far less comprehensive with far fewer examples and docs).

I was, coming from being mostly a highlevel language coder, suprised at how much I like working in this combo.

Low level stuff -> raw C. High level stuff -> Scheme, but written such that I can drop into C or move functions into C very easily. (The s7 FFI is dead simple).

It's just really nice in ways that are hard to articulate. They are both so minimal that I know what's going on all the time. I now use the combo in other places too (ie WASM). It really forces one to think about architecture in what I think is a good way. YMMV of course!

Re: Why I Always End Up Going Back to C

#34
post #26

Earlier quoted context omitted.

> It needs to use basic data structures, so it uses GLib. It also need to support runtime-defined connection graph, so it is built on top of GObject. That's running into the age old trap of trying to shoehorn an OOP system into C, just don't do that ;) E.g. don't design your systems around the OOP paradigm in the first place.

You know what gstreamer does, right? It's a dynamic multimedia framework - you give it pipeline defined by string, like: ximagesrc display_name=:1 ! video/x-raw,framerate=20/1 ! videoscale ! videoconvert ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast ! rtph264pay ! udpsink host=127.0.0.1 port=5000 and it automatically loads .so files, creates all those components and connects them to each other. Super…

This kind of automatic property serialization/deserialization, however, has traditionally been a sore spot for C++ as well.

You can do it, but you will have to either repeat yourself at least a little, use some very ugly macros, or use a code generator.

And many of those ugly macro tricks work in C as well. So do code generators.

That said, as C++ has added features, this type of metaprogramming has gotten easier and easier, and more and more distinct from C. This culminates in C++26 reflection which will finally make it possible to just define a struct and then automatically generate serialization/deserialization for it, without hacks. Once reflection is implemented and widely adopted, then I will agree with you that this should be 1 or 2 lines in a well-structured C++ app.

Re: Why I Always End Up Going Back to C

#35
post #16

Earlier quoted context omitted.

If software development taught me anything it is that everything that can go wrong will go wrong, the impossible will happen. As a result I prefer having less things that can go wrong in the first place. Since I acknowledge my own fallibility and remote possibilities of bad things happening I have come to prefer reliability above everything else. I don't want a bucket that leaks from a thousand holes. I want the leak…

This is, perhaps surprisingly, what I consider the strength of C. It doesn't hide the issues behind some language abstraction, you are in full control of what the machine does. The bug is right there in front of you if you are able to spot it (given it's not hiding away in some 3rd party library of course) which of course takes many years of practice but once you have your own best practices nailed down this doesn't…

Empirically speaking, programmers as a whole are quite bad at avoiding such bugs. Humans are fallible, which is why I personally think it's good to have tools to catch when we make mistakes. One man's "this takes control away from the programmer" is another man's "friend that looks at my work to make sure it makes sense".

Re: Why I Always End Up Going Back to C

#36
post #25

Earlier quoted context omitted.

How is one in full control of SIMD and CPU/OS scheduling in NUMA architecures in C?

Linux has libnuma ( https://man7.org/linux/man-pages/man3/numa.3.html ) while Windows has its own NUMA api ( https://learn.microsoft.com/en-us/windows/win32/procthread/n... ) For CPU/OS scheduling, use pthreads/OpenMP apis to set processor affinity for threads. For SIMD, use compiler intrinsics.

Nothing of that is written in pure C, as per ISO C standard.

Rather they rely on a mix of C compiler language extensions, inline or external Assembly written helpers functions, which any language compiled language also has available, when going out of the standard goes.

Re: Why I Always End Up Going Back to C

#37
post #2

C sounds nice if your task is simple enough, or at least if you can decompose this to a series of loosely-connected simple-enough tasks. But sometimes, there is an inherent complexity in what you are trying to implement, then C becomes way, way complex than C++. You build stuff, and there is so many manual steps, and none of them must be missing, or things will subtly break. A good example is "gstreamer", the multime…

People point to GObject say it's complicated and compare it to C++ classes. But the same thing as C++ classes in C would also be far simpler. GObject is so complicated, because it is essentially runtime creation and modification of classes (not objects, classes). Doing that in C++ will also be some work and look ridiculously complicated.

Re: Why I Always End Up Going Back to C

#38
post #3

> Code gets simpler because it has to, and architecture becomes explicit. > The real goal isn’t to write C once for a one-off project. It’s to write it for decades. To build up a personal ecosystem of practices, libraries, conventions, and tooling that compound over time. Each project gets easier not because I've memorized more tricks, but because you’ve invested in myself and my tools. I deeply appreciate this in th…

Agreed. I generally try to use C++ as a "better C" before the design complexity makes me model higher-level abstractions "the C++ way". All abstractions have a cognitive cost and C makes it simpler and explicit.

Personally, I tried that, but it already breaks down for me, once I try to separate allocation from initialization, so I am back to C really quickly. And then I want to take the address from temporaries or create types in function declarations, and C++ is just declares that to be not allowed.

Re: Why I Always End Up Going Back to C

#39
Returning to C after a decade away, I think the bottom line is that the reason why C has stuck around for so long is straight up path dependence. C is the foundation of Unix, and Unix-like operating systems took over the world, and C is a decent enough systems programming language that people started using it to write other OSes as well.

It bothers me that there’s some kind of mysticism around C. I keep seeing weird superstitions like, “modern processors are designed to run C code fast”. Or that there’s some inherent property of C that makes it “closer to the hardware”. The reality is just that C has been around for so long that there are millions of lines of optimizations handcrafted into all the compilers, and people continue to improve the compilers because there are billions of lines of C that will benefit from it.

FORTRAN is also crazy fast, but people don’t worship it the same way. SBCL and even some BASIC compilers approach the speed of C. And C is a high level language, despite what many people who have never touched assembler may assert.

C is not a bad language, and once you get your head around it you can write anything in C, but it’s absolutely full of landmines (sorry, “undefined behaviors”).

The author makes some really great points about the standard library. A lot of C’s pain points stem from memory management, string handling, etc. which stem from quirks in the standard library. And yet it’s possible to completely ignore the standard library, especially if you’re on an embedded system or bare metal. Personally I feel that a large standard library is a liability, and a much stronger property of a language is that the base language is small enough to keep the entirety of it in your head and still have the ability to implement any algorithm you need in a minimal number of lines without resorting to mental gymnastics, and still be able to read the code afterwards. I think this is why Lisp is so revered. I feel like Lua also falls into this bucket.

We need to stop starting flame wars about which language is best, cargo culting the newest shiny language, and instead just learn the strengths and weaknesses of our tools and pick the right tool for the job. You can machine almost anything on a lathe, but sometimes a drill press or a mill are much better suited for the task.

Post reply on HN