19 ms·
Switching to C over 'Modern' Programming Languages
- 0xfedbee 3y agoMore power to you. C is beautiful. Properly written C is more of an Art than Science. People who say C doesn’t work for large projects often forget that their cars run on C.
- coreyp_1 3y agoThis is how I feel about C++. It's enjoyable to use! I'm happy to use Python or JavaScript or something else when appropriate, but coming back to C++ is like sitting on your porch, enjoying a cool breeze and the relaxing after a hard day of juggling magic.
- dgan 3y agoI do have an occasional cozy feeling about the time where I was writing VBA for a french bank lol. I thankful that time is gone, but ! VBA is simple, and may be enjoyable to use!
- GianFabien 3y agoOther than assembly language, all languages embody abstractions. I find understanding certain abstractions hard going because they don't mesh well with my view of the problem domain and my design for solution's implementation.
- shrimp_emoji 3y agoYep. You think C is "low level", but it was once considered "high level", and the compiler does many things you don't want, and the standard's ambiguously-worded, and implementers have their own interpretations about the ambiguity, and also bugs in their compilers, and you eventually arrive at: "If you really want those instructions to happen in this function, without fear of magic, write them in assembly."
- raspasov 3y agoThen you realize that your CPU has hardware bugs, and you go design and manufacture your own CPU :).
- flohofwoe 3y ago> but it was once considered "high level" C's position in the "low- vs high-level" hierarchy arguable hasn't changed much since it was created. There were already higher level languages in the 60's (e.g. languages which abstracted the underlying hardware much more than C, but those weren't useful for writing an operating system in).
- kaba0 3y agoFrom what I have seen, there are two “contending” definitions for what is high-low level languages: one considers anything above assembly languages high-level, the other is less concrete, and would put for example managed languages into the high level category/towards that end of the spectrum, while C, Rust, C++ would be on the lower end, assembly even lower. I prefer the latter definition, as the former is, while objective, quite useless. The second definition could be expanded by a partial order between languages by “feature X can be emulated in it” with some caveats[1], and then we might even get Rust/C++ beat C for low-levelness, since C don’t have any way to force vectorization (compiler-specific intrinsics don’t count!). [1] since most languages employ FFI/linking, not even this definition is too specific — would probably have to write it as the “idiomatic language can emulate feature”
- throwawaymaths 3y agoThis is silly. Assembly is an abstraction too. Do you think the CPU actually runs the code you give it? Of course not. There's microcode, register aliasing, speculative execution, etc. Even assembly itself has symbols and labels, which are themselves abstractions.
- deleted 3y ago[deleted]
- flohofwoe 3y agoThe difference is that a CPU does way less magic under the hood than an optimizing compiler for a high level language, and there's no such thing as UB in assembly (outside some exotic cases like 'illegal' instructions on the 6502 which behave unpredictably)
- mprovost 3y agoMeltdown/Spectre pulled back the curtain and revealed just how much magic is going on with modern CPUs.
- Dylan16807 3y agoBut it only really manifests as timing.
- Brian_K_White 3y agoThis. The cpu magic doesn't do things you didn't ask for, or can't figure out how to ask for through a bunch of indirection. All the cpu magic means is that you don't know how it did exactly what you expected. It still produced exactly and only the expected output from the given input. High level language magic means it does things you didn't expect, and that you can have a hard time figuring out how to get it to do something you want if that doesn't happen to be one of the things the language designers predicted and decided for you that you should ever need to do.
- 3y ago
- tsimionescu 3y agoActually, x86 assembly also embodies plenty of abstractions. Not sure on ARM or RISC-V, but x86 assembly instructions are not executed the way you'd think by any modern processor. Essentially the processor reads a while bunch of instructions at once, splits each in the raw microinstructions, arranges them in a graph of dependencies, and then solves an optimization problem to find the best way to schedule nodes from that graph onto its internal execution pipelines. In real-world execution, you can't even tell what assembly instruction(s ) are the ones being executed at a partocular time - disparate parts of various instructions. Some instructions, like "mov ax, 0", don't even execute: they just serve to mark which the tens of real registers is now free to use for another symbolic register like bx.
- Brian_K_White 3y agoScheduling and implementation are irrelevant to the complaint being made about high level languages. No matter what the cpu does internally to arrive at producing the requested output from the supplied instructions, it DOES produce exactly the reqested and expected output from the given instructions. What it does not do is for example maybe a + operator doesn't mean the same thing after some unknowable prior step changed the definition of +, or flatly not provide a means to manipulate some data in a way that a language author thought was crazy and no one could ever have a valid reason to do $thing like idk execute a string or something. Sure there are now optional settings and features you could consciously use, for example to enforce that data/exec seperation, but it doesn't just do it by it's own magic according to someone else's rules instead of your own code.
- hdjjhhvvhga 3y ago> After looking up compatibility for SDL, I noticed it is able to run on iOS 6 and greater, meaning it supports iOS devices all the way back to iPhone 3GS. Whoah, I was convinced there is no way to write and run apps on these older iPhones - I wonder how difficult the whole process is.
- detrites 3y agoWhoever has downvoted this, can you explain why? I'm interested in this angle, and it quotes the article so therefore is on-topic. Can't find current info on it online.
- ihatepython 3y agoI don't understand using SDL, it's not that hard to write something in Objective-C that runs on earlier versions of iOS as well. You can even cross-compile from Linux, or even run clang directly on iOS if you jailbreak. My own experience is with iOS 4 - 6.
- kvark 3y agoDon’t expect to see immediate benefit from Rust by writing a small Pong application. Rust gives you confidence at scale: the ability to depend on many 3rd party blocks without compromising stability or performance, the ability to grow and maintain the code, collaborate on it, etc. Nothing of this is easily seen on a small self-contained program you can write in C.
- 1vuio0pswjnm7 3y agoI still cannot figure out how to easily write small applications with Rust on low resource computers, like the one I'm typing this from. (Limited storage, CPU, memory.) It seems even the smallest programs require a massive toolchain. The default reliance on network connection for compilation is offputing. It's vastly easier for me to write small programs, offline, with C. The rationale for using Rust over C that I see published the most is "memory safety". But I can write small C programs for text-processing using flex that do not manually manipulate memory. What benefit would there be to write them in Rust.
- tannhaeuser 3y agoThat's a point I was trying to make multiple times - that C (apart from O/S code and drivers) is used for small command line utilities and language runtimes of higher-level languages. Nobody (except maybe game devs) wants to develop fat application server binaries or other long running server apps in C++ or other non-GC'd environments (due to memory fragmentation issues alone if not other things). And for a language runtime, you can't use Rust's memory safety guarantees either. This leaves Rust for what it was originally invented - browser engines and fat desktop apps.
- Ar-Curunir 3y agoThere are tons of CLI utilities developed in Rust that are faster and safer than their C/C++ equivalents. See for examples ripgrep.
- Puts 3y agoC is used for the whole Linux kernel and not just "utilities".
- sakras 3y ago> There’s just so much “magic” happening in each that it’s difficult to figure out what’s going on. When I’m writing code in these languages, I realize my brain is effectively writing psuedo-C code and then transpiling to whatever language I’m working with. I feel the same way about these other languages, but for kind of the opposite reason! I write some code in the new language and then transpile it to C in my head just to see what I expect the CPU to be doing. I'm going through SICP right now and I find myself fighting the urge to imagine `cdr` as dereferencing the `next` pointer of a linked list. I spend a lot of time worrying about this stuff when writing other languages, probably to the detriment of my productivity.
- hnarn 3y agoIs this becoming a thing now (or maybe it was always a thing), where a language, like Rust, has become popular enough that instead of everyone talking about learning it, they now want to talk about how “simple” and “beautiful” C is for no other reason than signaling how different you are from the zeitgeist? Rust exists for a reason, and it solves specific problems. That’s the “magic”, just like any abstraction in any language. So what’s the argument, that abstractions are bad? Clearly not: > I also haven’t really experienced the problems Rust claims to be solving This is like hearing someone say 20 years ago that “I’ve heard a lot of good things about PHP but I don’t see the point of it, because I’ve never had to write a web application that interfaces with a database” — well, no shit?
- pulse7 3y agoMaybe the zeitgeist is "being different from others for no reason"...
- hnarn 3y agoThat’s a very good point.
- version_five 3y agoI started a side project in C earlier this year, and now I'm a little upset at the prospect that doing that is going to be seen as some hipster niche. I felt the same way when everyone started growing beards.
- raverbashing 3y agoYeah I agree These people (with rare exceptions) quite funnily never seem to have shipped some actual product or service based on those "simpler" languages. Or if they have it's shipping their parallel implementations of basic services that every language does better than C like strings, slices, data structures, etc. And no, if your code depends on cpp macro magic, it is not helping your point.
- spoiler 3y ago> they now want to talk about how “simple” and “beautiful” C is for no other reason than signaling how different you are from the zeitgeist? It sounds to me like they keep learning languages with the same illusions and failing to take any lessons between their language exploration escapades. All programming languages suck. It's just about finding the one that sucks the least for you (or your project/business). They made the comparison of RPG characters and mentioned endgame frustrations. In my experience, C is the epitome of endgame frustrations (C++ maybe being worse, depending on codebases you work on); they've just yet to discover that
- david2ndaccount 3y agoI’ve been enjoying writing libraries in C and being able to use them both from native applications and in web apps via WASM. I personally avoid emscripten and just implement the minimal C/JS glue and utilities myself.
- sjmulder 3y agoWhat library or such if any do you use for string.h/math.h/snprintf and such?
- david2ndaccount 3y agoFor snprintf I use stb sprintf [1]. For the reasonable functions from string.h (memset, memcpy, memmove), you can just use compiler builtins (__builtin_memset, etc.) as long as you enable the bulk memory extension (-mbulk-memory). I haven’t needed much of math.h for the stuff I’ve made, when I have I just called stuff on the `Math` object in javascript. [1] https://github.com/nothings/stb/blob/master/stb_sprintf.h https://github.com/nothings/stb/blob/master/stb_sprintf.h
- rootw0rm 3y agoI've been learning Rust lately. Working on a little game. First few thousand lines of code in I was having some doubt. After being a little frustrated with borrows and lifetimes and with my strong tendency to prematurely optimize all the things I was soooo tempted to just switch to C and have full unfettered access to my sweet sweet pointers. I'm glad I haven't switched though. Performance (which I'm measuring a ton of) is great. The situations where I wanted to bow out and take the 'easier' path were mostly bad design choices on my part and I think partly just laziness. Rust forces me to think a little bit more, and I've really enjoyed learning about how/why the various language features were designed. Now I'm one of those damned Rust evangelists that have been annoying me for years =)
- weinzierl 3y ago"Rust forces me to think a little bit more [..]" My reaction to that has always been that it forces us to think about the things we would have had to think anyways if we wanted to create reasonably reliable and secure software. So in the end if saves work, even if it doesn't appear like that at first.
- KyeRussell 3y agoThis is precisely what abstractions are meant to solve. If you’re needing to think about something “anyway”, then it’s a leaky abstraction.
- flohofwoe 3y agoThe other side of the medal (especially for game development), is that in the higher level parts of game code you need quick turnaround times for experimentation and tweaking, and most of that code won't even make it into the final product (so all the upfront time you spent thinking about proper architecture and ownership details is wasted up there). The traditional solution is to have different languages for different code layers (e.g. a compiled language for the low level parts, and an interpreted scripting language for the high level parts), but this comes with its own set of problems.
- 3y ago
- KyeRussell 3y agoThe author appears to be quite green behind the ears, which is fine! They’re certainly doing themselves a disservice by being so sure of themselves. There’s a lot here that feels right in the pocket of Dunning-Kruger ignorance. Being able to analyse the benefits of new tech at a distance (which is what the author is doing with their sterile toy projects) is not something that you can “fake until you make it”. It requires a lot of deep experience with different technologies, enough that you can pick up the common patterns of costs and benefits, which for the most part never change. This is exactly what OP is doing. Their big list of languages they’ve worked with is doing the opposite of what the author intends. All it says to me is that their bar is way too low, and that they do not understand the level of technological understanding required for a language’s inclusion in that list to mean absolutely anything in the context of this blog post. In all I’m not really sure what the point of this post is. By the author’s own admission they haven’t worked with much C. If someone doesn’t understand the value in a language that addresses the memory safety footguns of C, I assume that they’re at best inexperienced, or at worst part of the quite sizeable contingent of C developers that are in complete denial about the language / standard library’s shortcomings, especially with regard to memory safety, because it’d require them to admit that they themselves are imperfect developers.
- jbstack 3y ago> They’re certainly doing themselves a disservice by being so sure of themselves I didn't find the OP to be sure of themselves. See e.g.: "Admittedly, this would slowly go away as I gained more experience with the language." "This is likely because I haven’t spent enormous amounts of time in C/C++" "I will probably come out on the other side with a lot of the same feelings about C as other languages." "Maybe I will find the complicated syntax and rules of Rust are worth it."
- Barrin92 3y agoUsing a memory unsafe language in a situation where it's not strictly necessary is in my opinion not justifiable at all. It's the leading cause for security issues by some measures[1], incredibly hard to reason about and hard to debug. Honestly unless you have a really, really, good reason not to, use a managed language. If that isn't good enough and you want to be fancy use Rust and only if you've exhausted everything else start writing C. [1]https://www.zdnet.com/article/microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues/ https://www.zdnet.com/article/microsoft-70-percent-of-all-se...
- flohofwoe 3y agoThe opposite it also true though: Using a memory safe language where it's not strictly necessary is not justifiable (e.g. Rust is essential for implementing a sandbox - for instance a WASM VM, but not for code running inside that sandbox - because the whole point of a sandbox is that it can run untrusted, unsafe code safely).
- Fell 3y agoI used to love C for its simplicity. There was just no surprises, and the limited feature set enforced a certain programming style that also happens to run very well on modern CPUs. But the C standard library is just awful. It's so inconsistent and full of quirks you just have to know. Like how some string functions allow you to specify a size, while others don't. And how strtok keeps track of an internal state and behaves differently on subsequent calls. I wish there was a language that as simple and limited as C, but with modern (and portable) functions for things like strings, networking, graphics and so on.
- Brian_K_White 3y agoIt is as much the case that modern cpus have been designed to facilitate c semantics. C was designed for the cpu initially, but a lot of generations have happened since then, and there have been attempts to try other things, and by now the cpu is designed for c to run well on it.
- flohofwoe 3y ago> But the C standard library is just awful. This is very painfully true, but one 'killer feature' of C is that it is useful without ever using stdlib functions (except basics like memset, memcpy, ... which can be considered compiler builtins anyway). In more recent languages (even C++) there is no such clear distinction between the language and stdlib any more, which IMHO is a real problem (e.g. most of C++'s problems are actually stdlib problems, not language problems).
- pjmlp 3y agoBecause it was designed with UNIX API surface in mind, and also the reason why outside embedded and Windows everyone with a C compiler does POSIX, even crufty mainframes that are still being sold.
- unixgoddess 3y agocheck out hare-lang.org (still wip, but quite good already)
- frodowtf 3y agoWhat's the point of this article?
- hawski 3y agoFor some time I think about using Rust, but in a cut down manner. Ignore Cargo and most of its stdlib. Not to use traits. Allow myself to use unsafe once in a while. Basically a subset of Rust that would be just safer-C. I wonder if that would be effective for me. Maybe even compile times would be acceptable. I guess, I must just try. I am one of those that tried Rust, but guess back to C for my own projects. It's usually that I like to write smaller utilities and many quirks of C are not as painful. I like to write things that do not use dynamically allocated memory for example. Also plethora of available alternative C compilers for example something using QBE gives me a nice warm feeling. Yes, it is not all technical for me.
- nayuki 3y ago> The first language I properly learned was C in first year of my engineering degree. [...] My experience in the class solidified my belief that programming was what I wanted to do and forged a bond with the C language that I didn’t realize until now. I am highly skeptical that the author understands the full ramifications of undefined behavior, dangling pointers, platform-dependent integer sizes, and the myriad sharp edges of the C programming language. I don't disagree that, for example, Rust has a heavy syntax. But those exist for a reason. Those are the result of hard-earned lessons from phenomena like double-free (see ownership) and duck-typed templates in C++ (see traits).
- hussainbilal 3y agoYou ever get the feeling that C should be grouped with all the XML and (semantic) web technologies the W3C no longer has active working groups for? Maybe combine them to make a Spring-like framework, but for C? Long standing non-changing specs and standards should be married, and with children.