Hacker News new | ask | show | jobs
by badsectoracula 1075 days ago
I don't write C as much as i used to but i still write a lot of it, including new code. The reasons are:

1. C is relatively simple. Sure, not as simple as it could be (e.g. compared to something like Oberon-07) but in the grand scheme of language things, it is far on the simpler side of the spectrum. I can write a C parser relatively easy if i want to for example (and at some point years ago i did that to transpile a C project to C# to run under Sony's PSM platform that was based on Mono and allowed only C#).

2. Undefined behavior is annoying as it can break previously working code with newer versions of the same compiler (though language lawyers playing word games like the code already being broken are way more annoying - the code did the thing i wanted previously so as far as i am concerned it was not broken), but this is something that aside from "obvious" things (accessing invalid memory) i can probably count in my fingers the times i encountered in practice (i write "probably" because right now i can't remember any case, but i've being writing C for more than 20 years). Valgrind and Ubsan help with these so they are not much of a practical concern.

3. I find CPP macros to actually be very useful and a feature that a) i'd actually like expanded instead of being stuck in the 80s (let me store some state or have a loop, FFS) and b) were available on languages too (Free Pascal is a language i also use and does have some C-like macro support, which is more than what you'd find in other languages but still not to the same extent as C). D's mixins essentially being ubermacros are a thing that i liked with that language but sadly their stance on breaking things is something that kept me away from it.

4. A C compiler is available on pretty much everything that can compute things - or at least on pretty much everything i might think on targeting with C anyway (and chances are there are multiple C compilers instead of just one). If not, i can probably write a compiler myself - it'd be rather simple and not that great but i'd be more likely to finish it than a compiler for some other language.

4b. Very related, so it gets a "4b" instead of 5 :-P, but there are a bunch of IDEs and editors that "understand" C. I like IDEs, i like syntax completion, i like semantic highlighting, i like being able to easily rename an identifier, etc and C being easy to parse (see #2) means it has a lot of those. Let me correct that, i don't "like" IDEs, i love IDEs.

5. Most modern computers might not technically be like how C presents them to be, but they're close enough where any differences only matter if you're trying to perform microoptimizations to your microoptimizations - at which point you'd most likely be using a combination of compiler-specific heuristics and assembly code anyway.

6. In most systems where that'd be a concern, the C ABI is pretty much stable or at least there is a stable C ABI, allowing any code written in C to be usable by other languages as well as shared libraries to be able to expose an ABI that will remain backwards compatible and usable by other languages. Of course other languages can do that but they pretty much always do it through a C-fication of their APIs.

7. C compilers - even those that perform a dangerous (see #2) number of optimizations - tend to be very fast. I hate waiting the computer to finish doing things so i tend to prefer languages with fast compilers.

8. While i don't (always) need to maintain 30+ year old code, i do have existing C code that (seemingly, see #2) works and i don't see a reason to waste time rewriting that code in some other language. Even if it'd be broken chances are it'll be faster to fix it than rewrite it.

9. I am comfortable with C. For me being comfortable with a language important because it lets me focus on the thing i'm trying to use the language for instead of the language itself.

There might be other stuff i forgot, but the above should give you an idea why i personally write C. Though note that i don't see as any sort of perfect language, there are a lot of things i'd like it to do better - including the type system you mentioned as well as the compile-time code evaluation i wrote above, be it via CPP or by some other means - but it is good enough.

2 comments

About 4., there is already a preprocessor loop proposal for clang[0] and I think I have also seen it some obscure Qualcomm bluetooth chip compiler.

[0]: https://discourse.llvm.org/t/rfc-new-preprocessor-macro-dire...

> let me store some state or have a loop

This is arguably already possible, and was possible even before c99 added variadic macros. Although the code is a bit cumbersome to write.

It it technically possible in that C macros are supposedly Turing complete, but i mean i want something like being able to add a value to a variable, iterate through values (proper list would be neat but i'd be ok with a string of space separate values), etc.
> It it technically possible in that C macros are supposedly Turing complete

It isn't Turing complete, because it will always terminate, but you can make the execution time (number of execution steps) arbitrary large exponential in respect to the number of source lines.

There are a few libraries that implement that.

https://github.com/rofl0r/chaos-pp: Quite high level implementation, that supports arbitrary precision decimal base arithmetic.

https://github.com/camel-cdr/boline: Mine implements 8/16/32/64 bit arithmetic, and low level control flow.

You can very often get away with using unary numbers and/or constant expressions to work around the limitations without needing a library.

Got any problem in mind? I've got some time on my hands to problem solve.

> It isn't Turing complete, because it will always terminate

Well, i wrote "supposedly" because i didn't try it myself but found a post[0] that claims it is. The example is even about making loops.

But the point is that these aren't only way too hacky but also slow down compilation. I did use some of my own preprocessor hacks when i wanted to do some fancy stuff with it at the past to implement an RTTI system that allowed automatic serialization of structs with nesting and references and while it worked (x-macros FTW), it was cumbersome and slowed down compilation so much that at the end i found it both much simpler and faster (in compilation time) to replace a ton of preprocessor macros with a code generator and a couple of #includes that included the generated code.

[0] https://stackoverflow.com/questions/3136686/is-the-c99-prepr...