7 ms·
Why I’m Using C
- jcpst 7y ago“Why I’m using medium to write this article.” I was curious about this, but medium wants me to create an account to read it. Oh well.
- jasonpeacock 7y agoDitto, it's paywalled. > You’ve reached the end of your free member preview for this month
- ldeangelis 7y agoI always use private navigation to go across the paywall, it works well on Chrome and Firefox.
- mirekrusin 7y agoI fell into that trap and now with an account I also can't read it. I don't recommend creating one, you'll see the same annoying message but with "upgrade for $X/month to read it" message.
- duckMuppet 7y agoThe article: > Why I'm using C. The front cover of the “C Programming Language” book as I recall it from memory Why on earth would someone would pick C to start a new project in 2020? Surely there is a newer language with more shiny features that’s better right? Well I can’t speak for other people but I’ll tell you my reasons. First of all let me preface this by saying that of course this is a biased opinion and the language I pick for something depends on the context it’s going to be used in. For example; I doubt I’ll ever be reaching for C when writing a web service simply because the ecosystem around that domain isn’t great and I’m not itching to write my http framework at this time. But for games, more specifically cross-platform games C is a clear winner for me because it provides me with exactly the things I’m looking for which is reliability, simplicity and performance. Reliability This is the most important and only real non-negotiable requirement for me; the reliability and portability of the toolchain and the access it provides to system and device interfaces. Languages, especially dynamic ones and their runtime environments come and go like fashion. When your target platform suddenly gets deprecated from the runtime you’re relying on, well then you’re just fucked and out of luck. I’ve been in this situation before with multiple languages and I don’t intent to repeat history here so I need something stable, something will have a reliable toolchain available on all the platforms I could ever possibly want in perpetuity without having to worry about compiler bugs as I’m more than proficient in the art of introducing my own bugs. The ecosystem around C provides all of this. Even for the most obscure platform you can imagine there will be solid stable toolchain with a good set of native libraries that provide access to system and device interfaces for said platform. Performance While I will happily write software in slower languages without that much complaint, performance is fairly high up on the list when it comes to writing games. Avoiding cache misses is key to that, so having any kind of dynamic language with an interpreter is hopeless. Even in the best case scenario that the platform of choice provides you with one of the magical JIT compilers available today, they’re still magical black boxes which makes it difficult to reason about performance characteristics object boxing/unboxing and cache locality. Same goes for stop the world garbage collection, again there are some fairly impressive implementations out there; Go’s garbage collector comes to mind but it’s still a garbage collector and it will still lead to frame drops. If you have to use object pools to tip-toe around garbage collector killing the frame-rate then what’s the point of having one in the first place. Even for a low fidelity game filled with chunky pixelated goodness having more cycles gives you a lot of room to experiment and still have plenty of room to add copious amounts of extra juice. But It’s not just about running fast, battery life matters as-well. Fewer cycles means less battery consumption which is a major win if you ask me. As long as I can help it, I’ll do my best to avoid draining a user’s battery in five minutes. Lastly, when it comes to the web and mobile the executable size also has to be considered. While it’s not a deal breaker it’s a nice bonus that if you work on it a little bit C executables built with WebAssembly essentially have zero bytes of overhead by default. It might seem like a minor thing but it’s the difference between loading instantly and taking 3–5 minutes to load on a connection. Simplicity While it’s not a critical requirement, a nice thing about C is that it is an extremely simple language which is a nice welcome break from working in monolithic languages that get jam packed with new features every time someone on the design team or committee learns about a new feature in another language causing a paradigm shift until the next iteration which causes another paradigm shift leaving the whole ecosystem in a bit of a tangled mess. When I’m saying C simple I don’t necessarily mean easy. If you don’t know what you’re doing C will absolutely blow up in your face and make you spend the day trying to figure out what you did wrong. But again it’s a simple language so it’s really not too hard learning how to write well-behaved programs. Secure programs is a different matter but well-behaved programs are easy-enough. Now there’s definitively features that would be nice to have in C; I wouldn’t hate having quality of life things like arrays that don’t decay to naked pointers, modules or deferred statements for example but not having them aren’t total deal breakers. At the end of the day I prefer having a limited surface area in the language than having a language that gets in the way bringing absurd amounts of complexity and bad abstractions to the problem. This applies to any language in theory but certain languages encourage you a-lot more to be “clever” more than others. I prefer to be pragmatic because if one is trying to be clever when writing a program, then good luck because one needs to be twice as clever debugging and maintaining it in the long run. >
- imtringued 7y agoIt loads for me but the asynchronous loading makes it feel really slow. The page loads but it doesn't show the body until 4 seconds have passed. There is a 34KB image and a short text. It's kind of absurd how the asynchronous loading takes 3 seconds for a cached image.
- llarsson 7y agoBlock javascript on medium. Makes it much better, no nagging, no limitations... sometimes you miss an image or two, but the text is there.
- padthai 7y agoFor me this does not work anymore. What I do is redirecting the domain to the Wayback Machine.
- 32gbsd 7y agoNothing new really
- jonnypotty 7y agoYou would have been better off writting that in rust
- rvz 7y ago> Why on earth would someone would pick C to start a new project in 2020? Please ask yourself this before writing any code (For a cross-platform game). By just reading this, I thought to myself if I were to write a cross-platform game in 2020, Is C necessary to accomplish this? Perhaps anything C can do, surely Rust can do it safer and arguably better.
- timw4mail 7y agoThe biggest advantage C has over Rust is the sheer breadth of platforms. As a developer, I would always prefer Rust over C, if possible, but sometimes C is more realistic. In most cases, C would only be more practical on obscure or outdated hardware, though.
- jkoudys 7y agoPretty easy to integrate C libs as unsafe calls with rust's FFI. You're definitely in for an uphill battle if you have to manage a bunch of decade+ old makefiles with hundreds of special flags for each platform under the Cargo ecosystem, though.
- worldsayshi 7y agoI fear that we are slowly moving towards a situation where our underlying technology stack is written in languages that a diminishing number of people have seniority in. 96% of the Linux kernel is written in C (https://github.com/torvalds/linux https://github.com/torvalds/linux).
- mroche 7y agoThe GitHub counters are not always accurate. 97.3% (if going by C (imp+header) and Assembly) of the kernel is written in C, with the rest being written in Assembly. Everything else is config files, scripts, tests, or docs. GitHub reports C++ and Objective-C; those are just .h header files. Update: Got to my system so I could actually look at available files accurately: C Implementation (.c): 28269 C Header (.h): 20250 Asm (.S): 1323 Edits: Update section and removing "100% in C" and "5 sources files of assembly"
- mmoez 7y agoThe article without Medium paywall: https://hownot2code.com/2020/03/13/why-im-using-c/ https://hownot2code.com/2020/03/13/why-im-using-c/
- shamas 7y agoThat does give some food for thought. Of all the new language features, the elements I really need —functors, asynchronous syntactical sugar, and static null analysis— don't require much of the bloat found in many modern languages.
- SteveSmith16384 7y agoI assume that since he's writing a game, he's using some kind of library/engine/framework, but doesn't specify which one. This would affect his arguments for reliability (is the framework available on all these platforms?) and simplicity (how simple is the framework?). Maybe he's only writing an ascii game though.
- FpUser 7y agoMaybe he is using his own library. Not unheard of. One of my friends does for example
- tobyhinloopen 7y agoSDL is a common one, and is really easy to use
- systems 7y agoOk, I think since none of his reasons include I am doing system programming I will debunk Reliability: C is not the only language with a reliable ecosystem, and what should matter most is the reliability of the program, not the tools made to create the program, so in this regard, I think Rust, OCaml, C#, Java are all as reliable, and I would argue it is easier to write more predictable or reliable programs in them Performance: Yes sure C wins almost every performance benchmark, but Rust is very Fast and Ocaml is also very fast so unless you are working on system programming stuff, I think you have better options that are more reliable and predictable Simplicity: Here I would like to contrast simplicity of the tool vs simplicity of the product, complexity does not go away, complexity is abstracted, simple tool = complex product or process, complex tools on the other hand may allow you to create simpler tools and processes, if you use simple tools you will transfer complexity to your products, which I don't think is necessarily a good thing
- jkoudys 7y agoRust will frequently build code that will run in a comparable number of cycles, but can often run even faster as soon as you introduce concurrency. Safety isn't just some crutch to lean on instead of simply being really, really careful in C. Concurrent apps need a lot of guarantees for memory safety, and it takes a lot of mental energy to figure out how safe you really are. C devs often go overboard and do more than is necessary as a result.
- guggle 7y ago"But It’s not just about running fast, battery life matters as-well. Fewer cycles means less battery consumption which is a major win if you ask me. As long as I can help it, I’ll do my best to avoid draining a user’s battery in five minutes." I was thinking about languages in terms of ecology. I'm a Python fan and while its lack of performance never bit me in the real world, how many Joules would be saved if my apps were written in another language ? I'd love to see a study/comparison based on real apps (not algos implementations).
- turbinerneiter 7y agoHere you go: https://greenlab.di.uminho.pt/wp-content/uploads/2017/09/paperSLE.pdf https://greenlab.di.uminho.pt/wp-content/uploads/2017/09/pap...
- guggle 7y agoYes, thank you, I knew this study. I wonder how real-world apps would change (or not) the conclusions.
- manaskarekar 7y agoNot what you’re asking for, but here is a study that others may find interesting https://thenewstack.io/which-programming-languages-use-the-least-electricity/ https://thenewstack.io/which-programming-languages-use-the-l... Edit: just saw sibling comment linking to the same paper.
- guggle 7y agoMakes me want to learn more Go...
- exabrial 7y ago> Languages, especially dynamic ones and their runtime environments come and go like fashion. Sage advice.
- tonyedgecombe 7y agoHardly, Ruby is 25 years old, Python is 30, Javascript is 24.
- eddieh 7y agoWell, Ruby is waning, Python is surging, and JavaScript is peaking. How will this look in 5 years? How about 10 years? Would you say PHP is in fashion? How about Perl or Tcl?
- kerberos84 7y agoJava is here since 1995 and going nowhere in near future.
- eddieh 7y agoIs Java in fashion? This thread is about the fashionability of languages, not the age of the language.
- falcolas 7y agoWho cares about fashion? In 15 years Ruby, Python, JavaScript, Perl, TCL (particularly for building simplistic but effective GUIs), and PHP will all not only be usable, but actively used.
- eddieh 7y agoThis thread is about fashion. Did you read what the OP quoted? Here it is: > Languages, especially dynamic ones and their runtime environments come and go like fashion.
- leecarraher 7y agoi use c in scientific computing for small processor intensive routines that can leverage openmp's straightforward parallelism.
- vkoskiv 7y agoHave you considered using `phtreads`? It's part of the POSIX standard, and it's less cumbersome to use.
- jkoudys 7y agoYou'll build to almost the same number of raw CPU cycles executed for the code, but probably build a better-performing game in a language with safer/simpler concurrency/parallelism. Ever since futures (concurrency) has stabilised, rust's my first choice on this. Pretty much all of his points not related to the sheer age of C apply; you can even get the 0-byte-overhead webassembly if you go no-std, though I seldom forego something so useful that's smaller than the loading-screen background.
- bsenftner 7y ago> For example; I doubt I’ll ever be reaching for C when writing a web service simply because the ecosystem around that domain isn’t great and I’m not itching to write my http framework at this time. C has everything, including several top quality http frameworks. I use https://github.com/corvusoft/restbed https://github.com/corvusoft/restbed and find it more reliable, more performant, and "better" in all respects than the php, js, node, and whatever frameworks I've been forced to learn.
- megous 7y agoI was almost getting excited, but it's C++, not C.
- clarry 7y agohttps://www.learnbchs.org/ https://www.learnbchs.org/
- koffiezet 7y agoI have programmed in C for a long time (for embedded before everything became ARM+Linux), and unless you have technical reasons to use C for a new project, I would skip it. I like tinkering with the low-levelness of C, but what applications really need that these days unless you're working with hardware/os level stuff? There's also so much FUD about performance, but reality is that without numbers, you'll never know. Certainly for game development, unless you're working on a cutting-edge game engine, there's little reason to focus on performance first, and even then - most popular modern game engines offer interpreted paths for game logic. Fear of garbage collectors is also bullshit in most cases. Many don't realise a simple call to free or malloc (or new/delete in C++) can result in just as much unpredictable hick-ups, which is why many games engines use specially tuned memory managers, some even specifically including garbage collectors (see the Unreal Engine for example). Certainly in game development, flexibility to tune game mechanics is far more important to make a good game than performance, and creating such flexibility in a C application is a lot more complex/more work than in a higher-level language, and you'll end up building very high walls you really don't want to tear down and start over with.
- strategarius 7y ago"Reliability" - in a language with manual resource management and unsafe parallelism model? Really? BTW never heard of modern games written in C. Mainstream game engines (UE, Godot, Unity...) are written in C++ and C# and cover all major platforms and consoles. "Performance" - Rust is probably more performant when it comes to code, and definitely more performant when it comes to development time. "Simplicity" - primitivism is a closer definition.
- dragonsh 7y agoRust is not close to hardware as C is, so if need to do anything with hardware Rust still relies on majority of the code written in C. Performance wise today C is still faster than Rust in general. Rust is still a decade or more away from anything serious like C. Majority of the functional Rust libraries today depend on underlying C libraries. Rust may try to replace C++ but replacing C is far away dream. Let's wait when Mozilla (origin and major supporter for Rust language) can release Firefox in Rust, until than it's still a popular experiment in systems programming area. Rust does not run any critical component like Linux Kernel today, when it will be able to do it than it can be considered as real systems programming language challenger to C. Right now most of it's safety guarantees are not really battle tested like C.
- strategarius 7y ago"Rust does not run any critical component like Linux Kernel..." - and the only reason why it is not happening (provided that C and Rust have perfect interoperability, more and more C/C++ developers get familiar with Rust) is the fact that Linus Torvalds convinced by voices from Ethernet socket not to use anything but C. I can't wait for him to retire so that Linux kernel devs could pick up more modern toolset
- steveklabnik 7y agoIncidentally, back in 2016: https://www.infoworld.com/article/3109150/linux-at-25-linus-torvalds-on-the-evolution-and-future-of-linux.html https://www.infoworld.com/article/3109150/linux-at-25-linus-... > What do you think of the projects currently underway to develop OS kernels in languages like Rust (touted for having built-in safeties that C does not)? > That's not a new phenomenon at all. We've had the system people who used Modula-2 or Ada, and I have to say Rust looks a lot better than either of those two disasters. > I'm not convinced about Rust for an OS kernel (there's a lot more to system programming than the kernel, though), but at the same time there is no question that C has a lot of limitations.
- pritovido 7y agoI use C(as a backend) because I understand it. In reality I use anything that gets the job done faster. That usually means prototyping in C++,lisp, python, swift, java, perl, lua. After I have the prototype I code it automatically with C, or minimal C++ and my own DSLs, done in Lisp controlling C, C++ code generation. I have reinvented the wheel a lot. Someone told me you are not going to be smarter than a compiler, but having read several of them, they are so dumb, and they have to be because they are generic. E.G In a project I was using std::vector and predicted the expected performance of the whole program by O notation and "on the park" calculation needs as X. When I completed the program, it was X/1000. Fair enough I made some stupid mistake...in the end I got X/100 performance and could not optimize farther. I got so frustrated so I started replacing components to see if numbers improved. Replacing std::vector by a c vector made the program X/1.4!! So I started studying std::vector implementation and it was a template of a template of a template... I could not wrap my head around such a mess. My implementation was done in lisp with proper macros and was way simpler and efficient and generated c code, that was so easy (although tedious) to understand.
- klodolph 7y agoReading std::vector or most parts of the C++ standard library is the path of insanity. It puts you in touch with some fairly arcane parts of C++, and on top of that you have the allocator class, which std::vector inherits from rather than embeds because if it were embedded, it couldn’t be zero bytes (otherwise every object wouldn’t have a different address). By comparison, glibc isn’t so bad to read. Same with the standard library for Python, Go, Rust, etc… I have never had such a problem reading library source code as I have with the C++ standard library.
- ainar-g 7y agoIf this[1] article is to be believed, STL can also perform poorly in a debug build. [1] https://zeux.io/2019/01/17/is-c-fast/ https://zeux.io/2019/01/17/is-c-fast/
- BubRoss 7y agoIf a std::vector is causing performance problems there is some major disconnect between how it is being used and how it is meant to be used. Someone else noted that debug more will stifle performance, which is true and the most likely culprit. Other problems can include constant resizing and memory allocation and copying, but when something is 1/100th the speed it should be, that screams debug mode being left on, which will do bounds checking on every access.
- billfruit 7y agoWhile it is true that C perfectly matches the hardware, it imperfectly matches the rich software abstractions which are needed for moderate and large sized software. The lack of namespaces and sane object creation, destruction semantics etc, makes programming tedious. A large proportion of code in many large C programs go into recreating imperfectly the features that are by default provided by richer programming systems. And that repeats for every large program you do. It quickly becomes boring and unenlightening, to recreate an exception handling mechanism or data structure implementation for the nth time. Why would anyone not prefer not having to focus on the mere infrastructure, and rather direct directions on the interesting problems to be solved. Another thing is that large C code bases tend to become ensconced in layers of preprocessor macros, which I think is a hack-y way of doing things.
- jjgreen 7y agoC, besides its intrinsic beauty, does not fill you with the urge to tell others to pipe curl output into their shell; that's a win for me.
- tobyhinloopen 7y agoI like working with C. It’s simple and transparent. I wish I could use it more.
- johnklos 7y agoIt seems like many of the responses to this article are from Rust and other language fans (but mostly Rust). I think many people are reading what they want instead of what the author was trying to convey: "This is the most important and only real non-negotiable requirement for me; the reliability and portability of the toolchain and the access it provides to system and device interfaces." Rust isn't exactly reliable. Try to build Rust itself. There are all sorts of issues with resource consumption and parallelism, and it takes more CPU and memory than compiling an entire OS. Rust's portability is strongly discouraged by the resources it requires. Many platforms REQUIRE cross-compilation because they don't have enough memory, and this makes it hard to say it's easily portable. If you're a fan, you're easily going to overlook this. You probably don't care that more than half the world doesn't have computers which have the resources to run Rust. That's fine. You also say that people shouldn't be concerned with compiling their own stuff. That's fine, too. But there are people who like to create projects and write software that's as accessible as possible to most people, not just to some people and available to many others just as downloadable binaries. If you're not the kind of person who wants a free and open software ecosystem where everyone can participate, not just those with the resources to buy fancy, powerful, multigigabyte, multigigahertz, multicore 64 bit CPUs, then Rust is fine for you. If you you care about accessibility to as many people as possible, perhaps you'd come to the same conclusions as the author.
- loup-vaillant 7y agoIt seems you are working on a different set of constraints than the author's. The author was talking about making games. Those are generally proprietary, and even the free one almost always have binary distributions. Rust itself likely have a binary package for your development platform of choice. Likewise, cross compilation is likely not a problem. You don't develop on the PS4 or Switch, you develop for them. Sure, in practice, cross compilation in C and C++ is indeed a problem. I'm wondering to this day how that's even a topic. A compiler is just a goddamn translator, the target platform should naturally be independent from the source platform. Worst case, you need to recompile the standard library for the new platform. (I suspect this is related to the bewildering difficulty of linking libc statically.) You do have a point, but it's much broader and much stronger than choosing C over Rust. We spend heaps and heaps of code solving problems that could be avoided in the first place. Niklaus Wirth's Oberon operating system required less than 10,000 lines of code, and now we need like 200 million lines?! No way we now have 20,000 times the functionality, so we can guess that current computing systems are at least 100 times too big (that is, comprised of over 99% accidental complexity, Brooks be damned). I sometimes feel the only way to make software truly Free and Accessible (meaning, people have the right and the means and the ability to use & modify their software), is to remake everything from scratch, with the benefit of hindsight.
- glouwbug 7y agoThe great benefit to C is that it doesn't change. You won't feel tempted to rewrite your entire project 3 years later with the newest features
- IshKebab 7y agoI wish the myth that C is simple would die. It has all sorts of complex nooks and crannies. Even some basic things like specifying types are quite insane (e.g. for function pointers).
- loup-vaillant 7y agoC gives you an initial illusion of simplicity, and being close to the hardware. Then you learn about Undefined Behaviour.
- clarry 7y agoThe language would be more complex if it tried to specify all behavior. UB allows it to be simpler. Do not confuse simple with easy.
- loup-vaillant 7y agoI disagree. Much UB makes the language less orthogonal, and ultimately makes the specification longer. And more complex. Classic example of illusion of simplicity: signed integer overflow. Going outside the range? Undefined. Left shifting a negative integer? undefined. You can't just assume 2's complement, you have to be aware of the Nasal Demons compilers are becoming increasingly apt at summoning. Another one: out of bounds array index is undefined, even if there was something of the right type there: #include <stdio.h> #include <stdint.h> typedef struct { uint64_t a[8]; } blk; int main() { blk b[2]; for (size_t i = 0; i < 16; i++) { b[0].a[i] = i; } printf("normal : %lu\n", b[1].a[2]); printf("overflow: %lu\n", b[0].a[10]); // undefined return 0; } Depending on optimisations and compilers, you won't get the same result every time, and all sanitizers warn you about the UB. Conclusion: you can't assume a flat memory model, even on modern X86 in 32 or 64 bit mode. There are exceptions, depending on how you access memory, through which pointer. Again, your language specs just got longer for not defining what happens outside the bounds. --- Undefined behaviour simplified one thing: the compilers themselves. At least, until they got the idea to use UB for optimisation, and started to summon the Nasal Demons as a result.
- cartoonfoxes 7y agoCould we have a discussion about C without making it about Rust? The author doesn't mention Rust once.
- eatonphil 7y agoRandom note: every few years I update a list [0] of popular programming subreddits (by subscriber count) on the /r/programming wiki. Over the last two years, C increased in popularity overtaking Ruby. And C++ increased in popularity overtaking PHP. Rust, TypeScript, and Dart made big gains as might be expected. Swift didn't really move anywhere. The biggest surprise for me were how much the interest in C and C++ continues to grow relative to other high-level languages (that probably also have greater number of professional users). [0] https://www.reddit.com/r/programming/wiki/faq?v=0692c0d1-6174-11ea-98bc-0e55b58028a7&v2=1063c806-621f-11ea-8159-0e437a1ed589 https://www.reddit.com/r/programming/wiki/faq?v=0692c0d1-617...
- SteveSmith16384 7y agoI agree with all his arguments, as long as I'm only writing HelloWorld.c :o