7 ms·
I think the main weakness of this paper is that it doesn't really address why C is used in lieu of other "better-C" non-managed languages, such as C++, D, Nim,
by jcranmer 3y ago
I think the main weakness of this paper is that it doesn't really address why C is used in lieu of other "better-C" non-managed languages, such as C++, D, Nim, Rust, or Zig--it's almost entirely focused on the idea that the competitors to C are inherently managed languages, framing the question essentially as a "why C instead of Java?" which is a frustrating approach when you're asking "why not <language which is not Java in the same way C is not Java>?"
- quelsolaar 3y agoC is better because it doesn't try to program for you, it isn't clever, convenient, or have any ideas about how you structure or solve a particular problem. It gives you basic functionality and then gets out of your hair and lets you ge on with programming without making a grand statement about computer science. For people who actually like to program and don't want the language to do it for you that is pretty attractive. It also turns out that if you remove all the fancy abstraction and write everything out, the code becomes very maintainable and easy to manage. The fact that its about as portable as a program can be helps. I find that most people don't want to write C, but almost everyone is pretty happy interacting with C code written by others, because its simple, fast, portable, easy to integrate, and bind to other languages, and most non-C programmers can read it and have a rough idea of what is going on.
- jjnoakes 3y ago> C is better because it doesn't try to program for you, it isn't clever, convenient, or have any ideas about how you structure or solve a particular problem Why is that better though? I personally appreciate it when cleverness and convenience make my life easier, my programs less buggy and less likely to end up in a CVE, or point me toward better structure. > It also turns out that if you remove all the fancy abstraction and write everything out, the code becomes very maintainable and easy to manage History shows that this isn't true though, not in all cases.
- quelsolaar 3y ago> Why is that better though? Some people think so. Hence some where meant for C. > History shows that this isn't true though, not in all cases Not in all cases? I had no idea it was possible to write bad code in C, I must immediately switch to language where all code is always perfect no matter what the programmer does. History does show that most of the largest, longest running, most depended on open source projects like Linux, Apache, Git, MySQL, CPyton, OpenSSL, Gcc, Curl are written in C, so its hard to argue that the language isn't maintainable.
- PartiallyTyped 3y agoThe oxidizing of the Linux kernel has already begun, many of the core-tools have been rewritten in rust, large segments of firefox are written in rust, chromium is getting oxidized [1]. I don't think this is a sound argument because of survivorship bias. [1] https://security.googleblog.com/2023/01/supporting-use-of-rust-in-chromium.html https://security.googleblog.com/2023/01/supporting-use-of-ru...
- placesalt 3y ago>> History does show that most of the largest, longest running, most depended on open source projects like Linux, Apache, Git, MySQL, CPyton, OpenSSL, Gcc, Curl are written in C, so its hard to argue that the language isn't maintainable. > I don't think this is a sound argument because of survivorship bias. The argument is that those projects prove large C programs/systems are maintainable. 'Survivorship bias' doesn't enter into it; they are large and have been well maintained. Edit: I remember a time when "correlation is not causation" was the endlessly-repeated phrase. La plus ca change, la plus c'est la meme.
- PartiallyTyped 3y ago> The argument is that those projects prove large C programs/systems are maintainable. 'Survivorship bias' doesn't enter into it; they are large and have been well maintained. It shows that large C programs / systems can be maintainable. My claim is that the projects became maintainable out of necessity, that is, despite C, not because of C. Had C been opinioned around certain things and enforced maintainability out of the box to some degree, then and only then you could claim that C is maintainable, because this speaks for the general case. On the other hand, C is not opinionated about things, so you must enforce maintainability and high standards to get around all the footguns. This is what makes it unwieldy and why Rust is so loved. This plays greatly into the survivorship bias. You claim that C is maintainable because of all the large C projects that were forced to become maintainable. Had they not been maintainable they would not be as large or survive the test of time, and thus you wouldn't be able to cite them as evidence to your claim. In contrast, the oxidification of a lot of software, and the rise of "better C"s that have picked up steam shows that there are languages that are more maintainable and arguably better approaches for most software as they avoid all the footguns. NASA has strict requirements to make it maintainable, e.g. no heap alloc, so when you force yourself to not use language features, it appears that those features make things worse for you. Edit: Anyone care to inform me how my response falls into "low standards" for HN, and so much so that I got flagged and can not comment ?
- steveklabnik 3y agoI do think you’ve identified a significant rift between those that prefer C and those who do not. I think you’re being downvoted for the value judgement you’re injecting, though. > gets out of your hair and lets you ge on with programming This is the divergence, I think. For me, the method in which c “gets out of my hair” means that more burden is placed on me, the developer. Which means I have to work more slowly, cautiously, and remember things that a good type system could have been checking for me. And the lack of features means I spend time working around that lack rather than getting real work done. I suspect these preferences are irreconcilable.
- quelsolaar 3y ago> I do think you’ve identified a significant rift between those that prefer C and those who do not. I agree. I think the article is very right in identifying that C developers look at programming differently. I think that is a good thing. Even as a Die-Hard C programmer, I celebrate that people use other languages and especially that people are developing new languages like Rust, Odin, Zig and so on. I don't think it wrong for someone to reject C, if its not right for them. Do what works for you. I do think that given Cs massive success, people should perhaps be a bit more interested to figure out why, instead of just dismissing it so fast.
- comfypotato 3y agoYour comments on this thread up to this point sound like a religious fanatic. I greatly enjoyed reading. Goes to show why it’s called “The C Religion”.
- quelsolaar 3y agoI think, most designers of languages want abstractions, convenience, and clevernes. So for people who don't want that we have to cling on to C since there aren't other options ;-)
- rewmie 3y ago
- PartiallyTyped 3y ago> It also turns out that if you remove all the fancy abstraction and write everything out, the code becomes very maintainable and easy to manage. I was with you on everything until this part. I just don't see how reducing soundness via a weaker type system, and needing to explicitly manage memory vs e.g. Rust, uniq_ptr, shared_ptr, and so on makes things easier to maintain. I also don't see how absence of generics helps here either.
- westoque 3y agothis. properly made abstractions are actually more maintainable and easier to manage. for ex, take anybody learning programming about writing to a file, if you write your code using ruby, it would be a lot safer and maintainable than the C counterpart even though the latter is more powerful.
- rudedogg 3y agoAbstractions hide details, and you'll likely need to interact with something the abstraction hides eventually. So then you end up doing one of two things: 1. Learning every detail of the abstraction and the thing it's abstracting, fighting it until you persevere and get it to do what you want 2. Write something from scratch that does exactly what you need Going the #2 route from the start isn't such a bad idea, and has a lot of advantages IMO. The hard thing about all this is that abstractions are beautiful at first. It's not until you're far into a project, or doing something unusual that it all falls apart.
- bitwize 3y agoI think it's high time to bury the myth of the "bondage and discipline language". Study after study has shown that, comparing development of the same application in C vs. a language with a very strong type system such as Ada, the application in the language with the very strong type system costs less to develop and has far fewer errors. The fact that C "gets out of your hair", i.e., doesn't provide checking for certain kinds of correctness, is an anti-feature.
- jcranmer 3y ago> C is better because it doesn't try to program for you, it isn't clever, convenient, or have any ideas about how you structure or solve a particular problem. Oh, C very much does have ideas. One of the big problems I have with C is that it has a surprisingly limited feature set that makes it difficult or impossible to express certain programming styles. Want to describe a function that returns multiple values? Well, you can't really do that (especially if you want this to mean "use two registers"). How about using unwind to express exceptional control flow? Can't do that either. Or if you want a function with multiple entry points? Or coroutines? C's fundamental inability to express certain kinds of control flow [1] greatly limit your ability to structure your code in ways that might make the code clearer. > It also turns out that if you remove all the fancy abstraction and write everything out, the code becomes very maintainable and easy to manage. I think experience has shown that this is not the case. The closest kernel of truth you might find is that if writing code requires a certain amount of tedium, that tends to limit the scale you can grow a codebase to, and size is one of the largest drivers of complexity. While it's definitely the case that abstraction can decrease maintainability, it is a mistake to think that it necessarily does so. Indeed, abstraction is often necessary to make code more maintainable. For example, when I design APIs, I think very hard about how to design it in such a way that it's impossible to misuse the API. So I make my APIs distinguish between UTF-8 strings and Latin-1 strings, so you can't be confused as to what's in them, or even distinguish between a row number and a column number. The other thing to bring up is that we know quite well that humans are pretty bad at doing tedious, repetitive tasks with high accuracy. And computers are pretty good at that! What this suggests is that languages should be designed so that things that are tedious and repetitive--such as propagating errors up a stack, or cleaning up resources on failure--can be done by the compiler and not the programmer. As we've seen with things like gotofail, C is a language which lacks features that enable work to be pushed onto the compiler and not the programmer, and code written in C suffers as a result of that. [1] And there's even more exotic kinds that I could get into--this is merely the list of features available in languages you've probably heard of, maybe even used!
- kps 3y ago>Or if you want a function with multiple entry points? `entry` was a reserved word in K&R, but not implemented.
- em-bee 3y agoi haven't come across a single language that would limit me in how i structure my code. that is, i didn't feel limited. whether it was python, ruby, smalltalk or even lisp. heck, once i translated a program from pike to common lisp. the structure of both programs was identical despite everyone claiming that lisp is so much different. it can be, but it doesn't force you to be. most non-C programmers can read it and have a rough idea of what is going on that's because most programmers can read most other languages and have an idea what's going on. that's not at all a special feature of C.
- pornel 3y ago> i haven't come across a single language that would limit me in how i structure my code Rust is one of the languages that limits how the code and data can be structured. Often it's either the Rust way, or it's going to be awkward or not even compile (e.g. it doesn't like doubly-linked lists, structs containing a references to their own data, mutable getters, and a few other common patterns). This is often very off-putting to people coming from C who want to do things their way, and end up fighting with the compiler over every line of code.
- em-bee 3y agoi haven't had an opportunity yet to work with rust. it is something i want to try. i actually like the idea of being constrained and forced to find different ways to solve a problem because i think i can learn something from that. i guess that haskell should be equally challenging. i actually expected that challenge from lisp too, but i was rather disappointed to discover that this wasn't the case and lisp isn't really that much different, neither was smalltalk. it's a nice language, but message-passing doesn't feel any different from method/function calling, so it's not really a different paradigm that affects the structure of your code.
- kazinator 3y agoIn Lisp, you can just use what you know and not challenge yourself; you're not constrained or forced. Any such challenge has to be self-imposed. You can learn enough to be able to work in it, and then just use it like Fortran.
- JohnFen 3y ago> C is better because it doesn't try to program for you, it isn't clever, convenient, or have any ideas about how you structure or solve a particular problem. This is much of why I prefer to use C (well, I actually prefer to use C++-as-a-better-C, but since I'll omit almost all of of what C++ brings, it's still C for all intents and purposes). Other reasons I prefer C include producing small executables (and, more importantly, being able to effectively control executable size), that it is the most portable language (in the sense that there are C compilers for just about every computer platform in existence), and it is both readable and concise.
- fulafel 3y agoAvoiding the UB footguns does steer you pretty hard if you try to write secure & portable C. For example keep away from signed integers and dynamic memory & pointer arithmetic.
- rramadass 3y ago> It also turns out that if you remove all the fancy abstraction and write everything out, the code becomes very maintainable and easy to manage. This is key to the success of C (also the main reason stated by Linus Torvalds for his choice of the language). You can write really complicated code which may take time to unravel/comprehend but nothing is really done behind your back nor hidden (please let's not start with UB :-).
- arghwhat 3y agoI like Rust, but I wouldn't categorize it as a "better-C". It is a whole different world, and some things work well in Rust but not in C, and vice versa. Many things are flat out uncomfortable to express in Rust, and the number of times you need to bail out and just Rc<RefCell<T>> or Arc<Mutex<T>> random things is a bit high. Interacting with anything but basic C is also horrible, requiring significant engineering efforts to hide the glue in a binding crate when possible, and sometimes it just doesn't work out. Many C libraries are heavy on linked lists of linked lists with their own lifetimes, and that's Rust's kryptonite. Zig is definitely a "better-C", but also young and not nearly as widely adopted.
- steveklabnik 3y ago(You’d never want the box in either of those situations, as the data is already boxed by the Arc or Rc)
- arghwhat 3y agoYeah got a bit carried away, and was stuck in C-ffi land where things get weird - Box::leak, ManualDrop, PhantomPin wrappers, all that.
- jcranmer 3y ago> the number of times you need to bail out and just Rc<RefCell<Box<T>>> or Arc<Mutex<Box<T>>> random things is a bit high. People keep saying this, but in all the Rust I've written, I've never needed to reach for this. Indeed, from what I've seen in the community, this kind of nesting is often a code smell that maybe you should think about the architecture of your system a bit more. > Many C libraries are heavy on linked lists of linked lists with their own lifetimes, and that's Rust's kryptonite. One article that was on here earlier today discussed what's the usual Rust salve to this problem, handles: https://news.ycombinator.com/item?id=36419739 https://news.ycombinator.com/item?id=36419739. That is to say, instead of saying that everything is a pointer, instead make an arena (an array) of allocations and use indexes into that array instead. This is the solution in petgraph, for example.
- throwawaymaths 3y ago2017, so zig was very much a baby. Rust was still young.
- Joel_Mckay 3y agoThe historical answer was fairly simple: 1. C was slightly more understandable than existing options at the time 2. The compiled objects could be manually verified/debugged with relative ease 3. There was no mystery/interpretation between the runtime and the hardware, but this isn't technically true anymore for many platforms. 4. The simplified environment demands simplified structural design. Try anything fancy, and C can be very unforgiving to the uninitiated (easier to write bad code). Do a one liner in high level languages instead =) 5. Due to the well-defined simpler syntax of standard C89, the GNU groups were able to bring opensource/free compilers to many new platforms. ARM popularity, Linux, android, and most IT infrastructure owe their existence to these compilers... even if it was just bootstrapping the new environment. 6. All languages have use-case specific tradeoffs. I have worked with over 54 different languages, and have observed the following: if your code still builds and runs on a 5 year old OS, than it will likely not need refactored for another 5 years. As Intel begins to deprecate x86 legacy features, there will be a lot of drivers that will need rewritten. Have a wonderful day =)
- anacrolix 3y agoThe Lindy Effect for programming languages.
- rramadass 3y agoVery clearly put!
- kazinator 3y agoC was not more understandable than existing options at the time. You know that cdecl program to explain C declarations? There never was a pdecl for Pascal, or mdecl for Modula or what have you. C is terse and cryptic; and that's what appealed to some of the programmers. You could get the machine to do what you want and---bonus!---programmers not versed in C cannot read your code! This would have been a selling point to assembly language programmers: switching to C would be like a lateral move to a different priesthood.
- fulafel 3y agoAlso at the time compilers were expensive proprietary things. Ease of compiler implementation was big and enabled low barrier to entry. The allowance for variation in semantics, like data type sizes lowered it too.
- faiD9Eet 3y agoI would like to attempt an explanation. It boils down to learning complexity. > why C is used in lieu of other "better-C" non-managed languages, such as C++, D, Nim, Rust, or Zig I am a system admin. I do not earn my income writing code and therefore spend at most a few hours a week programming. I've spent about 1000 hours writing C code in my life. About 200 hours of Golang. Years of Posix Shell. Years of Perl 5. I've had a little exposure to Java and C++ and Haskell. I have read a few examples of Rust. C++ has a higher complexity than C. C++'s syntax is more powerful, it has an additional paradigm (the C++ template system), and if you mix in QT you have one more paradigm (QT preprocessor), it has a very wide ranging standard lib (which data structure do you use for lists? vector, dequeue, ...) augmented by QT and augmented by boost. C++ is huge. There is no way I will learn that in my professional life, I simply do not have enough hours of training left. C++ is not a valid successor to C, because its complexity hinders acquiring the language. Rust suffers the same complexity as C++. I will not have enough hours on my learning schedule to acquire a proficient level of Rust. Golang is nice for me personally. The book "The Golang programming language" is only double the size of "The C programming language", which makes them comparable in complexity. I get stuff in Golang done faster than in C since I find debugging easier. I have neither used NIM, nor D, nor Zig. All I can tell you is that C is sexy because the language is small and therefore one can acquire it in a life time -- without being a full time programmer.
- brokencode 3y agoC is “small”, but the amount of footguns and unnecessary complexity is incredibly high. Where’s a hash set when you need one? Or an automatically growing list? Pretty much any simple task is difficult in C. I would recommend beginner programmers start with something high level and widely used like Python way before C, even though Python probably has the longer manual. You can learn the basics relatively quickly and be much more productive than in C.