8 ms·
In the 1970s, the alternative to C was assembly. In fact, I can remember hearing stories of the fights needed to pry every-day, normal developers---not systems
by mcguire 3y ago
In the 1970s, the alternative to C was assembly. In fact, I can remember hearing stories of the fights needed to pry every-day, normal developers---not systems programmers, not power users---off of assembly to a "higher level language".
It wasn't until the 90s that it became clear that C was not appropriate for applications work (and this was in the era of 4-16MB machines), although that took a long time to sink in.
- daymanstep 3y agoWhy is C inappropriate for applications work?
- TillE 3y agoTry writing a generic, reusable data structure in C. It's agony.
- bluetomcat 3y agoYou don’t need to write generic and reusable data structures in C. You write a data structure suited for the problem at hand, which often means that it’s going to be simpler and more performant because of the known constraints around it.
- grumpyprole 3y agoIt could be more performant because of the known constraints around it, or it could be an ad-hoc, informally-specified, bug-ridden, slow implementation of half of some data structure. At least with a generic and resuable data structure you have a known reliable building block. Again, performance over safety.
- commonlisp94 3y ago> It could be more performant No, it almost always is. The designers of a generic library can't anticipate the use case, so can't make appropriate tradeoffs. For example, compare `std::unordered_map` to any well written C hash table. The vast majority of hash tables will never have individual items removed from them, but a significant amount of complexity and performance is lost to this feature.
- SubjectToChange 3y agoNo, it almost always is. A library author can spend ridiculous amounts of time refining and optimizing their implementations, far more than any application programmer could afford or justify. The designers of a generic library can't anticipate the use case, so can't make appropriate tradeoffs. This is definitely not true. Take C++ for instance, not only is it possible to specialize generic code for particular types, but it's absolutely routine to do so. Furthermore, with all sorts of C++ template features (type traits, SFINAE, CRTP, Concepts, etc) even user-defined types can be specialized, in fact it's possible to provide users with all sorts of dials and knobs to customize the behavior of generic code for their own use case. This functionality is not just a quality-of-life improvement for library users, it has profound implications for performance portability. For example, compare `std::unordered_map` to any well written C hash table. std::unordered_map is a strawman. There are a plethora of generic C++ hash tables which would match, if not soundly outperform, their C counterpart. Also, even if we blindly accepted your claim, then how do you explain qsort often being beaten by std::sort or printf and its variants being crushed by libfmt? What about the fact that Eigen is a better linear algebra library than any alternative written in C?
- commonlisp94 3y ago> A library author can spend ridiculous amounts of time That's true. But simply having knowledge of the goal and a few simplifying assumptions can beat all the optimization in the world. In other words, a polished sub-optimal approach isn't as good as just having a better approach. `std::unordered_map` is heavily optimized, but can't make any tradeoffs because it's a general tool. > plethora of generic C++ hash tables which would match, if not soundly outperform, their C counterpart. Post one. > not only is it possible to specialize generic code for particular types, but it's absolutely routine to do so. Yep, it can do type base specialization, not application based specialization though. That requires a programmer. > how do you explain qsort often being beaten by std::sort a standard library C function often cannot be inlined to remove the comparison function pointer call, whereas std::sort trivially can. If you wrote one yourself for a particular problem, it would not have this issue. This is actually a great example of where C excels because the choice of sorting algorithm so much depends on the kind of data you are sorting. Let me be clear about my claim: tailor made solutions to each problem will almost always be faster than generic solutions. Do you really disagree with that? If you want to argue that maybe it's not productive to work that way, that's a different argument.
- NavinF 3y agoThat must be why every C project has its own string, dynamic array, hashtable, etc. It's definitely more performant to have several different implementations of the same thing fighting for icache
- overgard 3y agoTo be fair, most C++ projects (outside of embedded and games) use STL for string/dynamic array/hashtable, and while that standardization is certainly convenient I'm not sure STL is generally faster than most hand written C data structures, even with the duplicated code.
- commonlisp94 3y agoIt's a nice thought, but in practice C binaries are orders of magnitude smaller than any other language. Also compilers make that tradeoff for inlining all the time.
- mcguire 3y agoEntirely true. Unfortunately, that comes at a cost of programming time and effort and a decent amount of risk.
- StillBored 3y agoAgony might be a bit much, and i'm not trying to defend C because this is one of the strong reasons for using C++/STL... But, generally one should just reach for a library first before doing a complex data structure regardless of language. And for example, the linux kernel does a fine job of doing some fairly complex data structures in a reusable way with little more than the macro processor and sometimes a support module. In a way the ease of writing linked lists/etc are why there are so many differing implementations. So, if your application is GPL, just steal the kernel functions, they are reasonably well optimized, and tend to be largely debugged, are standalone, etc.
- sn_master 3y agoTry doing the same in Go and it's even worse.
- commonlisp94 3y agoThat's writing some other language in C syntax. You use arrays or you write a specialized version for the use case.
- memefrog 3y agoWhat does that have to do with writing an application?
- grumpyprole 3y agoThe technical arguments should be obvious, e.g. spending ones complexity budget on manual memory management and avoiding footguns. But one amusing anecdote is that the open source GNOME project founders were so traumatized by their experience building complex GUI apps in C (already a dubious idea 20 years ago), that they started building a C# compiler and the Mono project was born.
- seabass-labrax 3y agoIn 2023, you'll be hard pushed to find a GNOME application actually using C# and Mono. The vast majority of GNOME components are written in C, with a large number of them written in Vala and some in Rust and JavaScript.
- grumpyprole 3y agoIt was indeed a big yak to shave. Cloning a Microsoft technology probably wasn't a good idea for OSS adoption either.
- seabass-labrax 3y agoI'm sure; there are still threads that come up from time to time in GNU circles about whether Mono is actually FOSS (TLDR: it is), in which those of a more paranoid personality allege an EEE attempt by Microsoft. If this were the case, Microsoft clearly did not succeed even without Java as a legitimate competitor! Interestingly, Mono has had most success from its use in the Unity game engine.
- memefrog 3y agoYou don't spend "complexity budget" on manual memory management. Manual memory management is much simpler and easier than trying to manage complex arrangements where things are being allocated and deallocated all over the place, all the time. Gnome programs are largely still written in C, but it isn't actually C. Not really. It's glib, which is almost a whole new language written on top of C. It's its own little world and it's not a good world. For example, it calls abort() whenever it fails to allocate memory.
- mcguire 3y agoThe short answer is that C makes it easy to do things that you probably shouldn't ought to be doing. (The the answer to the opposite, "what work is C appropriate for?" is systems and embedded stuff, where doing-things-you-probably-shouldn't is largely the name of the game.) Another answer is that C doesn't have much in the way of guardrails; in a world where programmer time is much more expensive than machine time, guardrails make programming much faster.
- memefrog 3y agoEvery language makes it easy to do things that you probably shouldn't be doing. I don't know how many times I've seen naive accidentally-quadratic string handling code in high level languages, for example. Your answer is just buzzword after buzzword. What makes C bad for writing applications?
- Thiez 3y agoIn the 1960s they already had languages such as Lisp, Fortran, Algol, Basic... Even Pascal is two years older than C, and ML also came out around that time. The statement "the alternative to C was assembly" is simply incorrect.
- marcosdumay 3y agoOn practice those were either proprietary or required beefy machines that the people writing C couldn't get. On the limited environment where C got created, it was the only option. And everybody suddenly adopted that limited environment, because it was cheap. And then it improved until you could use any of those other languages, but at that point everybody was using C already.
- grumpyprole 3y agoIIRC, Mac OS Classic was written in Pascal, as were other operating systems. C just won the popularity contest.
- marcosdumay 3y agoThat was about a decade after C had already won.
- grumpyprole 3y agoThe Xerox Alto was early 70's and that GUI OS was written in Pascal. I always thought Pascal was better designed and less bizarre than C. Null terminated strings were particularly a bad idea.
- marcosdumay 3y agoOh, by 73. Impressive. I didn't know that. Still, that was a much more powerful machine than the ones people wrote C for. And when the cheap segment of those "fridge computers" became powerful enough to run whatever you wanted to put on it, people started using small workstations. And when those workstations became powerful enough, we got PCs. It's only when the PCs got powerful enough that we could start to ignore the compiler demands and go with whatever language fit us better. (The later reductions all were based on cross-compiling, so they don't matter here.)
- overgard 3y agoThe sheer amount of software that you're likely using right now that's written in C would seem to contradict your claim.
- SubjectToChange 3y agoThe market share of C in desktop, server, and other "enterprise" applications has drastically dropped since the 90s. Nowadays it's quite rare to see C chosen for new projects where it isn't required. In fact, despite of how pervasive it is, a huge amount of C code cannot be built on a pure C toolchain, i.e. C is essentially like Fortran.
- mcguire 3y agoIt still hasn't entirely sunk in. :-) Plus, legacy code.
- pjmlp 3y agoOnly inside Bell Labs, the world outside was enjoying high level systems programming languages since 1958 with the introduction of JOVIAL.
- mcguire 3y agoWhere by "the world outside" you mean DoD contractors?
- pjmlp 3y agoEveryone that was using JOVIAL, ESPOL, PL/I, PL/S, PL/X, PL.8, PL/M, Mesa, ALGOL 60 and 68 based languages, Modula-2, Solo Pascal, Concurrent Pascal, Lisp, BASIC compilers,.... Burroughs, IBM, DEC, Xerox, ETHZ, MIT, Intel,....
- Gibbon1 3y agoWhen talking about hot path optimizations though assembly is still a good alternative.
- memefrog 3y agoIt's quite clear to me that C is appropriate for applications work. Most applications I use on a daily basis are written in C (and were written after the 90s), and most of the rest are written in C++. What makes you think you can't write applications in C?
- mcguire 3y agoYou obviously can, but doing so takes a considerable effort. Not making that effort leads to lots and lots of bugs.