Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Learn C in 2023?
222 points by 0x008 on Dec 23, 2022 | hide | past | favorite | 211 comments
Hello,

I always have the itch to learn C, juts because it was such an influental language and when you are digging around a lot in GNU/linux you will have contact with it one way or another.

What is the way you would suggest learning C in 2023? I am already familiar with other languages (rust..) but would like to have an introduction to the C basics and program some hands-on projects in C, so I can learn the pecularities of the language.




https://www.learn-c.org/

If you have lots of time: https://hal.inria.fr/hal-02383654

If you can't be bothered reading a whole book: https://matt.sh/howto-c

Exercises: https://www.codestepbystep.com/problem/list/c and https://exercism.org/tracks/c

Once you have syntax and basic algorithms down well, watch this, the only 2 hour YouTube video I'll ever recommend: https://m.youtube.com/watch?v=443UNeGrFoM

Both r/cprogramming and r/C_programming are active, also full of lazy students trying to get people to do their homework. If you come by, describe your problem well with code. Say you're learning for yourself, not for school.

Together C & C++ is a good Discord if you prefer live chat: https://discord.gg/tccpp


From the learn-c link:

    /* draws a point at 10, 5 */
    struct point p;
    p.x = 10;
    p.y = 5;
    draw(p);
I wish that would be a bit more 'modern', for instance:

    struct point p = {
        .x = 10,
        .y = 5
    };
    draw(p);
...or even:

    draw((struct point){ .x = 10, .y = 5 });
...main reason being that this avoids any accidents with unitialized data if the struct grows (the compound literal initialization makes sure that any struct members that are not mentioned are set to zero, while with the 'old school' approach you might end up with random junk in the struct).


I also love designated initialisers. C99 ftw.


+1 to https://hal.inria.fr/hal-02383654. It covers the language in extreme depth, and you likely won't remember it all on a first read but you'll walk away with a pretty good general understanding of the language. Plus, the author is an active contributor to the language.

I love C. As dangerous and as tedious it can be for large projects, I think it's my top choice for solo endeavors that don't require too many string manipulations. I don't think any language has come close to achieving the same balance of elegance and simplicity--maybe scheme? (zig comes close but has a substantial number of features that move it away from simplicity (e.g. payload capture))


> Once you have syntax and basic algorithms down well, watch this, the only 2 hour YouTube video I'll ever recommend: > https://m.youtube.com/watch?v=443UNeGrFoM

Hard +1 on this!

I think Eskil Steenberg work in C is really top notch - the video is heavily recommended, as is an overview of his work in general, he does some awesome stuff with C.


#c on libera is a genuinely helpful place full of neckbeards.


Sorry if this is silly question but what is libera?


It's an IRC network. https://libera.chat/


A sibling comment already mentioned what it is so I'll not repeat that. Just some additional context if you're somewhat familiar with IRC. It's the spiritual successor of Freenode after it was taken over by a member of that community.


#c-jeopardy is great fun as well.


Any recommendations on static analyzers, unit tests, coverage for c? Can clang tidy give hints about modern c they way it does about modern c++?


Not exactly your question, but valgrind is an amazing tool. It does execution-time analysis of your code and provides an in-depth report on memory usage. It will find and report memory leaks, use of uninitialized variables, bad memory references, etc. I love programming in C, but there are a lot of ways to corrupt memory, get segfaults, etc. valgrind is a useful and powerful way to guard against many of these kinds of problems. C++ is no better. The way I see it, programming in C is like lying on a bed of nails. Doable if you are very careful. With C++, they put a sheet over the bed of nails.


I haven't used valgrind in years, more used to asan, but I've been told it can do things asan can't?

Edit: to stretch the metaphor, modern c++ is like a thick rubber pad on the bed of nails, but often on the job you are hot bunking and you don't know which c++ your predecessor used to make the bed... Or you are in a hurry and you aren't sure which one you grabbed.


If you're used to ASAN, think of Valgrind like ASAN, TSAN, MSAN, and UBSAN all at once at the same time, and then has other facilities like profiling.

In any situation where I have control of how the code is built, I personally prefer to run those various SANs instead of Valgrind, usually three parallel builds: one with -fsanitize=address,integer,undefined, one -fsanitize=thread if more than one thread is involved in the project, and one -fsanitize=memory too if Linux is available. That gets you almost all the benefits of Valgrind faster than Valgrind.

But Valgrind is still an exceptionally powerful tool to learn and use. Its chief advantage to me is to be able to work with an unmodified binary. Its chief downside is it can be slow, and occasionally you may run into issues with support for more obscure instructions like vcvtps2ph.

MSAN is really the star of the sanitizer world, and is worth spinning up a Linux VM for. It tracks the initialized-ness of all your data and catches any use (really, branch) on anything uninitialized. I like to think of ASAN as "did I get my pointers right?" and MSAN as "did I get everything else right?".

If you're not familiar with integer sanitizer, it's like UBSAN except it checks for things that are often mistakes rather than things that are actually undefined. The most common situation I've found is code that's hashing data will often pop up a warning about unsigned integer overflow, which I choose to suppress as finely grained as possible with something like __attribute__((no_sanitize("unsigned-integer-overflow", "unsigned-shift-base"))). That way you can still find unintentional unsigned integer problems (e.g. with size_t).


Ideally you use both, as both can find some more obscure issues the other may not. At least in the past. Either in isolation also works well, though Valgrind is really a suite of many tools.


Don't bother with this stuff (or with "modern C") if you're just beginning to learn the language. You don't need it for small programs. No one is going to yell at you if your first effort isn't perfect. And no one is going to yell at you if you read the "wrong" book, or try things out in the "wrong" order. Pick any learning resource and get started now. You'll probably get distracted and move on to something else. Come back to it later or not.


Well C was my second language. I learned it on an amiga 500. But I quickly transitioned to a 386 (yes i know, a downgrade) but my dad put turbo c++ on it and I never wrote much ansi c after that. A bit for odd embedded targets, but mostly c++ my whole career. So I can write old fashioned c, and I don't start new projects in c, but writing c abi shims for c++ libraries or reading modern c is something I do with some frequency. Learning it would be fun maybe as I've never really used c99 or newer for anything.


My comment is for the OP, not for you. Go nuts learning C tooling and have fun.


Do bother with this stuff, it's super helpful and helps you understand your mistakes. Writing C without using sanitizers is like playing a game on hard mode, even for simple programs (especially when you're still learning).

You may leave static analyzers for later though, since they're more likely to bother you with unimportant stuff - but not much later.


I’m not sure, it does help to even just know about whether your program is faulty, and C doesn’t like telling it you, or in unintuitive ways only.


Set warning level to max, use clang static analyzer or clang tidy (I'm not quite sure how those two relate to each other though), and especially ASAN (Address Sanitizer) and UBSAN (Undefined Behaviour Sanitizer) (and if you write threaded code: TSAN (ThreadSanitizer).

One thing that Apple did right in Xcode and where other IDEs lagged behind is easy access to those tools from the UI.


That sounds like all the things I do for c++. One thing I really like is that clang tidy can flag the "old way" to do stuff. Was hoping it had that for c.


You can't rely on one tool, different ones catch different things. No one tool is best.

I usually use "-Wall -Wextra -Wpedantic", the GCC static analyser "-fanalyzer", cppcheck, and Clang scan-build.

That's good enough for my personal projects.

I have a couple of blog posts about this:

https://superjamie.github.io/2022/05/24/c-static-analysis-to...

https://superjamie.github.io/2022/11/04/c-static-analysis-to...


One useful tool is running clang or gcc with —Werror -Wpedantic which will point out a lot of things which are useful to know about, even if occasionally a false positive.


What is your opinion on K&R?


It's great for what it is, but the language and style have come a long way since then. It would be better to learn "Modern C" (this is the title of a book but also at least learn C99 not K&R C).

E.g., people like the book by Jens Gustedt. I'm ambivalent about it, but it sure machine-guns the important points.

[1] https://hal.inria.fr/hal-02383654/file/ModernC.pdf


> not K&R C

K&R the 2nd edition of book teaches ANSI C. (It is still the best intro into the basics of C.)


Not the person you are replying to, but here are my thoughts. It sounds like OP is looking to learn C for historical and contextual reasons, and for that K&R is perfect. The history of C is very K&R-centric.

For modern, practical C programing it is missing a lot though. It is a short, simple, from the original authors introduction to the language itself. There is nothing about how to test your code, how to set it up for long term maintainability, how to mitigate some of the security downfalls or even any of the features added since C89.

It's a good technical book. A great one for it's time and subject matter. But that caveat is important, it needs to be taken in context of the time. It shouldn't be the first, and absolutely not the only, book you read if you are writing modern production C in 2023.


> or how to mitigate some of the security downfalls.

I think I'd go further, there are places where it advocates downright unsafe practices. Eg. It's been a long time, but I thought I remember it introducing gets() unironically, without any caveat. For those that do not know, there is no safe use of that interface possible.


If you're just beginning with C, it doesn't matter. If anything, it's better to be exposed to these unsafe practices and make mistakes with them in the very safe environment of your own home, where absolutely no one cares what you're doing.

K&R C is an excellent learning resource primarily because it's extremely strong pedagogically. Read K&R and then move onto something else later when you're done with it. If you eventually get a job doing something with C, then you'll learn on the job what's important to the job you're doing.


I've taught C at university level, and used to give crash courses to new college grads and interns in industry.

The one thing I impart the most from the beginning is to develop good instincts for secure interfaces. You should be able to look at function signatures and see alarm bells for unsafe practices. For someone skilled at C this is second nature, you can see bad practices from a distance, often at the function signature level.

I think it would be unwise to neglect this.


It's unwise to neglect it in the long run. It's perfectly reasonable to ignore it initially. There are different valid pedagogical approaches here. Your approach may be suitable for the type of student you were interacting with, but the profile you're familiar with doesn't represent every person who might be interested in learning C.


I think a good approach is to have someone able to review code. So they can experiment and make all the common mistakes, then have feedback on it.


C is one of those things that unless you have proper testing, tooling and linting you don't know if you code is incorrect. It may have subtle memory bugs, rely on undefined behavior or crumple in exploitable ways under bad input. Having a feedback loop is really important in learning and improving. Undefined behavior helps subvert it.

For the exact example of above, how would a developer learn not to use gets? The best place would be a section on red flags in API design in the book. If you don't have that you need to find it through experience. Lints, fuzzing, sanitizers can help, but once again, none of this is covered in K&R. Some of it just didn't exist at the time or if it did, it was very primitive compared to what we have today.

Developers could pick up bad habits and be productive for years with them before they get bit by them. I know I did. I look back at some of the practices I picked up when first learning and cringe a bit. Especially since I think a fair amount of that code is still in production.


All of this is true, but if you are just starting with C, none of it matters.

If you continue using C, then you should eventually learn this stuff, but to overburden someone with a list of 100 things they must do right is the surest way to frustrate them to the point where they give up.

If OP eventually writes C code that goes into production for a company, it is the company's responsibility to have procedures and safeguards which ensure that OP writes reasonable code. Ideally, one such safeguard will be a senior colleague to introduce them to the thornier parts of C.

To expect a beginner to learn all of the finer points of a topic from the start is bad pedagogy.

On the other hand, K&R provides a set of exercises which are fun, graded, interesting, and challenging. By the time you finish them, you have a working knowledge of a large and useful subset of C. You can then proceed to reading another book (or consulting some other reference). Invariably, you will find that they disagree with K&R to some extent. Learning to spot these differences and begin to understand how C has evolved is itself an important lesson.


> If OP eventually writes C code that goes into production for a company, it is the company's responsibility to have procedures and safeguards which ensure that OP writes reasonable code. Ideally, one such safeguard will be a senior colleague to introduce them to the thornier parts of C.

You've mentioned something like this in reply to a few comments in here. This is a strange argument. It isn't too much to ask of a book to lay down more of a foundation so you don't need a 1 on 1 tutor later to correct misconceptions.

I get people like K&R because it is short and easy to read. Some subjects aren't best served by short and easy to read. The subject was well served by it when C was new and novel. We live in a very different world.


You don't actually seem to be addressing the quoted text... but I can reply to your arguments.

Sure, it would be ideal if there were a new book on C which did a better job of explaining some of the developments since K&R 2ed was written. If that book exists, I'm not aware of it. All of the books I've seen recommended are either too long, or poorly written. K&R's strong advantage isn't that it's short, it's that it's very strong pedagogically.

A "how do I learn C?" thread comes up on HN about once a month. In each of these threads, people will steer people clear of K&R, quoting something or another about how K&R isn't appropriate for this day and age (note: you do not explain why you think it isn't appropriate!). The tacit assumption here is that you can only read one book, or that if you read a book which isn't "perfect", you are somehow tainting yourself with corrupted knowledge. I think this is nonsense. An important meta-skill for learning is the ability to discern between good and bad information. The only way to build that skill is by consulting multiple sources.

Note that in my actual reply to OP, I don't specifically advocate for reading K&R, but instead to take a multipronged approach where you primarily draw from whatever learning medium you're most comfortable with. Most people I know that are in their early 20s or younger prefer learning from videos (I'm a math teacher and have lots of experience with people this age).


I think you've got a bit of a strawman in your head. Look back up at some of my comments you are replying to, namely the top one in this chain. A friend describes this as "violent agreement." I agree that it can be best to have a multipronged approach. That's why I said "It's a good technical book. A great one for it's time and subject matter. But that caveat is important, it needs to be taken in context of the time. It shouldn't be the first, and absolutely not the only, book you read if you are writing modern production C in 2023." I also address its short comings in that post.


I didn't read your other post. Glad we're in violent agreement!


I kinda disagree. global hidden state under APIs is a really awful idea to put in someone's head.

I think it also presents the notion to neophytes that there is magic under there


Unfortunately, global hidden state is an unavoidable fact of programming. I don't see how one could be very good at programming if they were kept blissfully ignorant of it. Sometimes there is magic under there, and you just have to do your best to empirically figure out how that magic works.


libc has a few interfaces with implicit global storage. This leads to lack of thread safety and other issues. A good library will let the caller provide storage for these cases, or provide the caller a handle with which to pass it later/free it.

A trivial example would be strtok vs strtok_r. There are some, like, say, asctime(), that operate against a global string buffer.

Sometimes interfaces "look like" they're returning a global buffer, for example readdir(), but that structure can hang off the DIR* struct ... Nonetheless there is readdir_r()


It's much too awkward IMHO, C99 and onward almost feels like a whole new language (mainly because of struct literal and designated init support).


Not being forced to declare symbols in the beginning of the scope is the real game changer I say. K&R or C89 without e.g. GNU extensions is really annoying to use.


Idk about that. I think it's code with everything declared at the beginning of the scope is easier to read and understand. Every time I see code written in this style (Git, Linux) it's easier to build a mental model of what is happening.


It's one of the best examples of technical writing in the field. A good introduction to the basics of the language. Read it for culture.

Read something else for safe C writing in a modern environment. Books like Modern C and Effective C are good starts.


It's wonderfully written. I'm a big fan of both Dennis Ritchie and Brian Kernighan personally.

However the book was last updated in 1988 and I prefer C99+ for almost every feature it adds. If I'm going to recommend just one book it will be something newer.


I'm not a C engineer, but I think I have an interesting recommendation to consider.

Since you are already familiar with other languages, you obviously don't need to know the basics of C. The basics are the same everywhere. Instead, you'd likely want to build that mindset on how to build good software with C.

I suggest you read other people's code and try to deep dive into the whys.

I heard Redis is a well-written software.

    git clone https://github.com/redis/redis.git
    git log –reverse
    git checkout ed9b544e...
We can now see the very first commit made by Salvatore Sanfilippo. From here, we can start exploring. By looking at the commit diffs and git log messages, you'll be able to understand the motivation behind the changes.

When you read a book, the most interesting parts are usually after all the theory is explained at the beginning. Somewhere in the middle of the book they start showing you code samples and that's when things become really interesting.

What I like about the reverse git-log approach is that it immediately throws you into the middle section of the book. This approach is both fun and eye opening.

Good luck!


For me, when I learned more than 20 years ago, reading source and manpages from Linux and other Unix like projects was a source of inspiration.

I'd recommend OpenBSD libc. https://github.com/openbsd/src/tree/master/lib/libc

String functions especially are a good way to get into the C way of thinking. Since C's approach to strings is unique.

I also learned a lot by reading manpages of libc functions or Unix utilities and thinking about how they were implemented, and writing my own little versions.


This. But for C++ and Python.


Fully agree with the principle but maybe let's not call Redis "well-written" :)

Redis is a great piece of software because of how much it impacted the "evolution" of Internet not because of the code quality, Redis's code resemble spaghetti code, a lot.

I will push myself and say that nowadays people would get fired for writing code like that!

And before someone start to throw stones (just for the sake of it), here a few examples: - Redis source code is FULL of GIANT files with thousands and thousands of lines of code, decoupling and separation of concerns are basic things! A few examples -- https://github.com/redis/redis/blob/unstable/src/module.c -- https://github.com/redis/redis/blob/unstable/src/cluster.c -- https://github.com/redis/redis/blob/unstable/src/redis-cli.c -- https://github.com/redis/redis/blob/unstable/src/networking....

- talking about auto generated, the repo contains commited auto generated code, a valid reason though really slips my mind (yes, of course I can think of a few, but ... really? :)))

- https://github.com/redis/redis/blob/9c7c6924a019b902996fc4b6... ... that struct feels like an "Italian minestrone", basically a kind of soup where you throw in, literally, all the vegetables you have around and it's great for a soup, a bit less for software engineering though :)

- the naming structure is a bit random at times, there is a mix of camel case, camel case mixed with underscores from time to time, pascal case

This kind of staff might be alright for a 0.3 or 0.4, maybe even for a 1.0, definitely not for a 7.x that has had 15 years to evolve :/ Even in cachegrand, that hasn't got to a v0.2 yet, I tried to avoid these kinda of dramas, in C is quick and easy to get there if you are not careful.

There are plenty of other small things but most of the big dramas should be there.


Re: auto generated code: it saves ci time which is a pretty huge benefit. You still need to regenerate the code to make sure it's up to date, but you can do that in parallel with tests that rely on that code.


This is a valid reason, but makes sense for code bases where the generation takes tens of minutes or more not seconds.


Here's one example of when to commit auto-generated code: if you use a tool like Cython and want to distribute sources to an end user, it is frequently recommended to distribute the C sources generated by Cython instead of the Cython code itself. The given reason is that the end user may not have access to Cython, but will likely have access to a C compiler. (This is frequently the case on scientific clusters where users don't have superuser privileges.)


Importing a C file into a Python session is a practice that can ---easily--- cause ---a lot--- of headaches, the packages required to build the code as python library and make it importable will vary between systems and make it hard to debug in case of crashes. I personally would distribuite the pre-compiled binaries, CI + docker makes that much easier.

The fact that "can be done" doesn't necessarely mean that "it's the right way" to do it.

Going back to embedding auto-generated code, focusing on this specific case, are you telling me that a line in the requirements.txt, on a machine where the user is expected to have access to a compiler, is the reason to keep auto generated code in the repository? Sorry, personally it seems a flaky reason.

Also, the very fact that you mention that users don't have superuser privileges should be even more of a reason to use virtual environments, where you don't need super privileges, or if you can't or want to use virtual environments you can still have multiple paths in the PYTHONPATH env variable and you can install packages in a specific paths leveraging the --target of pip or the PYTHONUSERBASE env variable, solving the issue as well.

I would prefer to suggest my users to improve their runtime environment than enable them to improve the chaos.


I don't agree that it's a good practice, I'm simply quoting one example to you since you mentioned you were not aware of any. IIRC, you can find many GitHub issue threads on the Cython repo where they go into more detail. It has been a while since I spent any time thinking about this so the details are no longer fresh.

Unfortunately, suggesting that users improve their runtime environment is frequently a nonstarter for different reasons. (One obvious reason: users either don't have time or technical experience to do so.)


Well I tried it and ed9b544e... is god awful, documentation has so many typos. God file 'redis.c' with 3k lines having even commented out code and some comments that I would not pass my code review.

But I love it and it is great recommendation.

Going to move with commits to see how it unfolds :)


I think this is important just to get the idioms down that you otherwise only get on the job. Could pick almost any big active C project. I used to do this and I’d see some construct I didn’t understand and consult my K&R book to learn it. I’d do this in parallel with a book though for sure, K&R preferably. C is so basic that if you pursue it further it will be about learning the projects/companies way of using C.


I've got a single digit number of contributions to projects that I like, mostly because of how daunting it is to familiarize oneself with a codebase, and this 'git log -reverse' trick seems incredible as an entry point to a new project.

That being said, how do you feel about using this technique for repos with 2k+ commits? It seems unrealistic to read all of them, or am I being short-sighted here? I get demotivated just thinking about it.


Reading 2k+ commits is a big waste of time.

Forcing yourself to read every commit to a project you "like" in order contribute to it is putting the cart before the horse. Just because you "like" a project doesn't mean you will have the skills to contribute usefully to it. This isn't a bad thing. I "like" GCC, but I don't have the skills to contribute to it. I'm not losing any sleep over this, and I'm definitely not thinking about reading every commit to GCC in chronological order.

If you use a project, you might find a bug or some deficiency in it. Then it might happen that you have the skills to quickly fix this problem. Either that, or this bug causes you so many problems or slows you down so much that it becomes worth it for you to develop the skills to fix the problem.


I like this approach to FOSS contributions, thanks for the answer, sfpotter.


I'm not sure why GP's post is upvoted so much, IMO it's a bad way to learn. I would instead find an entry point, a self-contained task that doesn't touch a lot of the codebase that you can use to learn something. Then, as you get more comfortable with some part of the codebase you can expand your scope by looking at tasks that touch other things. In general reading code is 50% of the work, the other 50% is to play with the codebase or try to make changes to it and see what happens.


That sounds reasonable, and I do agree that inching forward seems like a more viable approach to contributing in FOSS.

Thanks for the answer.


It's funny because I would never think that this is a good way to learn a codebase. Code changes completely through time, and early phases where nothing is set can be extremely messy and filled with constant refactorings. Commit messages are rarely good. I would rather try to learn a codebase looking at the latest state and the docs.


> It's funny because I would never think that this is a good way to learn a codebase.

It is NOT for learning the codebase.

It is for learning how to program in C.


Ah I see. I might try that with another language then! That makes more sense.


I did that with Git itself. As a bonus you’ll learn more about a tool you’re probably using everyday. If I remember correctly, even the early commits were pretty high quality.


FYI, missing a second dash

  git log -–reverse


Damn, what a great comment.


If you're fluent in Rust, you will have no problem learning C considered as a language. If C has any faults it is that it is too simple. Rust even sensitizes you nicely to the worst pokey bits of C, so you won't be wandering blind through the landscape of memory safety like most people learning C. I don't think you'd need books or anything, just grab some tutorials online and start banging away. It's not a hard language.

I say "C considered as a language", because in my opinion and experience the real challenge in learning C is C considered as a platform, that is, learning how to build C projects, how to actually pull in dependencies, how to resolve them when they blow up, how to build cross-platform, understanding the several toolsets used by real projects to accomplish these tasks (raw make, autotools, cmake, etc.), dealing with library conflicts, etc. C is a nice little language, too simple for 2022 and something I wish people would really stop using, but it is at least simple. The C platform is a clusterfuck nightmare disaster zone, if not multiple independent clusterfuck nightmare disaster zones.

I can say with a straight face I "know C", inasmuch as I know the language and have even done some non-trivial work in it. (Not much, but some.) I have never in my career learned C as a platform. This is a choice, and I still think it was even a good choice, but what I'm really highlighting in this post is that this is certainly something that is noticeable, that the fact that I "know C" has actually been of almost no utility whatsoever when I encounter problems and have to fix them because the problems are almost always in the platform. I have made do with a very cobbled-together understanding of the situation and a high degree of "google-fu" on this topic (beyond just "pop the error message in verbatim and hope for the best") and I've chosen not to pursue this any further.

So I would recommend to you that you consider your goals here; do you want to "know C" as a language or a platform? Both are fine options but they lead to different solutions.


> the real challenge in learning C is C considered as a platform, that is, learning how to build C projects, how to actually pull in dependencies, how to resolve them when they blow up, how to build cross-platform, understanding the several toolsets used by real projects to accomplish these tasks (raw make, autotools, cmake, etc.), dealing with library conflicts, etc.

Agreed. This is what's prevented me from learning C by contributing to large projects. I've always had trouble understanding the dependency management and build system of every project, as it seems everyone does it differently.

I kinda wish someone made a "C/C++ for Rust Developers", "CMake for the Rest of Us", or similar text that focuses enough on dep management and build systems.


There wasn’t historically a C “platform” in the sense you describe it here due to C’s age. Rust built itself around a single “platform“ because Rust was built in the 21st century. (Python and Ruby didn’t have “platforms” either, but they had uncommonly useful standard libraries.)


Agreed, though often paying (not open source) C projects have much simpler build requirements because the company controls the hardware. Last time I got paid to write C on a non-trivial financial app, all we did was call make with exactly 1 external dependency.


Programming in C can turn you into a very disciplined programmer for the simple fact that you will need to track when you request memory and when you need to free it. Essentially you will become the garbage collector. I would recommend you to the read classic "The C Programming Language" (Kernighan & Ritchie) and "Expert C Programming Deep C Secrets" (Van Der Linden) which will get you far enough to write useful programs. I read half of Gustedt book and it has good advice, probably need to pick it up again. A good starting point is to implement your own data structures, like lists, double linked lists, dynamic arrays (had a lot of fun implementing this one). Also (this is personal preference) I would learn a bit of the autotools, they are painful to learn and feel kind of ugly, but once they are in place you basically will forget about a ton of things and your build will become a joy (there's a nice book by No Starch Press about it). I've managed to integrate Check (https://libcheck.github.io/check/) so now I have unit tests in C which is something nice.


I don't recommend learning how to use Autotools unless you need to work on a project that uses it (and even then, try to avoid it).

Highly recommend learning CMake or Meson instead.

If you're just getting started, there's no need to tie yourself into knots learning "how to set up a project the right way". It's a waste of time. Your time would initially be better spent just calling the C compiler directly. This will help you learn a bit about the compilation and linking phase and will expose you to the C compiler's flags---useful skills for debugging automated builds later. Once you get to the point where you are working on a larger project, then you will be in a better position to decide what build tools are most useful for you.


> If you're just getting started, there's no need to tie ...

Yes, this is sane advice! Note that I'm not promoting autotools, I personally suffered it a lot before I got it for my builds, but is a tool that can be reliable across platforms. Yes I would leave the "how to set up a project" for the time when you really need it, no need to spend time on this if you're learning a language.


I have a C project I picked up (and got working thanks to help from HN users) that was heavily dependent on Autotools. I wanted to be able to compile it under Windows and couldn't make heads nor tails of it. After guessing and tweaking a config.h file to replace the one it didn't create, I was finally able to get gcc to compile everything using a batch file.

Eventually I'll be purging Autotools, make and all build systems, replacing it with a single batch file that wipes the slate then compiles. It only takes a few seconds to run, and removes a huge set of dependencies.

I hope to port the code to run under the Cosmopolitan library so I can be cross-platform and more.


I disagree, I find autoconf and automake very pleasant in operation. Mainly due to the OOTB support for things like bindir, libdir, and so on, all properly documented via /path/to/configure --help.


You probably don't need autotools as a beginner but if you intend to study those it makes no point starting with cmake. This is more of a C++ crowd thing with tiny mindshare among C programmers.


This. We called K&R as "The C bible" for a reason at Uni.


I’m also a traditionalist and I think the classic K&R C Programming Language book is the best way to learn C—you also get an understanding why C and *nix-based systems seem to go so well.


I love books, even if I don't finish them, especially the technical ones. Today we're very used to recommend sites and youtube videos as primers for learning. In some situations that is ok but I wouldn't hesitate for even a second if I have to choose been something online or a book.


Deep C Secrets is one of the best programming books ever written.


+1 for "Deep C Secrets" - excellent book. I don't use C enough to judge if it has stood up to the test of time, but I loved reading it.


Modern C by Jens Gustedt is quite good. This video gives a good overview of some modern patterns in C:

https://www.youtube.com/watch?v=QpAhX-gsHMs

I think the best thing you can do is go find a unit testing library you like the look of, maybe some tools for address/leak sanitization, and spend a good amount of time learning CMake and creating a build/project workflow you're happy with. Coming from Rust you've got great tooling and good guardrails in place to keep you on the happy path, I think getting into that groove early in C where you can run experiments and break things in a sane environment is important.


Came also here to recommend this book. You can obtain it for free at the authors site: https://gustedt.gitlabpages.inria.fr/modern-c/

If you like it you could buy the print version.

There are some things he writes that are a bit controversial but generally I think it is very thorough. Sometimes it felt a bit dry to read to me.


The thing about C is that its library call API is generally how different languages interoperate: If you write a library in [insert language here] and you want it to be callable in any other language, you need to make bindings for C.

Likewise, if you're using any other language and you want to use a general library, you'll need to know enough C so that you can successfully encapsulate concepts like pointers; and copy your program's data into data structures that C can consume.

It's all much, much easier if you have some C experience.

In my case, I haven't done much C in 20 years. What really helped me "keep up" was occasionally doing Mac programming in Objective C. Because it's really easy to drop into C, it helped refresh me on a lot of the concepts. Even if you're doing Swift, you can mix in an class written in Objective C that's mostly straight C in the methods.


Write a CHIP-8 emulator in C!

In my opinion it’s a perfect project because:

- it is a good size. You can be done in 10-20 hours, or longer if that’s your pace (have fun!)

- a lot of examples and community support.

- you have a whole project without any overwhelming complexities: you’re just taking inputs, reading some data, running it through a switch statement, writing data, writing to a screen, then repeating.

- you have lots of “test code” aka games.

- it mostly lacks tedium: you’re not repeating ideas too often

- it’s fun!


“can be done in a weekend”

RIP me who has spent 3 weeks on this

Great project for sure though!


haha I guess a “weekend” is a fuzzy unit of measure. I’ll amend.


I recommend C Programming: A Modern Approach by K.N. King http://knking.com/books/c2/index.html. My favorite part of this book is the exercises at the end of each chapter.


One of my favorite professors. His programming language concepts course was the most useful useful class I took in university.

I also recommend his book.


One thing I always loved about C was how easily you could slip in and out of x86 assembler with the __asm__ tag. There is no ceremony & it seems like magic. Like if you have 3 C int's a,b & c, and you want to add a & b and store the result in c, you would do:

__asm__ ( "addl %%ebx, %%eax;" : "=a" (c) : "a" (a) , "b" (b) );

Then you could just continue in C as if nothing had happened, and a printf("%d",c) would give you the right result. When I worked as a quant, I saw such code snippets quite frequently. Those days (late 90s early 2k), individual programmers had a certain amount of freedom that is completely missing today. You would have a cohesive team with a C programmer, java programmer, a sysadmin, an R guy, a kdb/q quant - no issues. The front end was all java awt widgets, and you would jni to do the hard bits. jni would pull in the C code, which was peppered with little bits of __asm__ to speed things up. Everytime you needed to interact with the outer ecosystem, C would do an fwrite to the file system, then R would pick up the file, do its montecarlo simulations & write back to the filesystem, the algotrading bits would be in q, and even the sysadmin had his share of awk/sed to massage all the back & forth data. It was smooth & nice & pulled 100x its weight. Best of all, the individual programmers had respect for each other's skills & would learn from each other. These days, some asshole CIO would fire the whole bunch & replace them with 10 pythonistas & insist everything should be coded in one true language - and as one of those pythonistas, while I am happy I still have a job in this recession, it is kinda sad, those languages were so much more fun & it was exciting to watch the interplay of different languages bearing their own strengths, whereas python otoh is so terribly boring & everyday is same verbose torch.autograd.Function crap oh well back to the coal mines.


Man, that is one complex, interconnected and interesting System!

I would love to work on something like that even if it is just maintaining a legacy product. Seriously, let me know (contact in my profile).

On similar lines, I have been thinking of using Erlang/Elixir for distributed programming over the Web (even in the browser if possible) and dropping down to C/C++ and J programming languages as required on individual nodes.


If you like such systems, backend systems in investment banks is where its at. Most of my experience was at Goldman, but similar systems exist in Morgan, Deutsche, Citi, UBS, Bloomberg or old PE firms. Look for C programmer careers in trade publications like efinancialcareers.com, or work with Huxley, Selby Jennings etc. Combination of C/C++ and certification in Q/kdb - will keep you employed pretty much into your 60s. Those languages are intrinsically hard & imo a real pleasure to code in. Well, I liked it.


Thanks for the pointers, appreciate it very much.


A main issue with learning C is getting the architecture right (header and source files), and figuring out the tooling for compiling and debugging and building (gcc and gdb and make/cmake for example). I like C in a Nutshell 2nd ed (Prinz/Crawford) 2016 as a reference for any questions about that:

https://www.oreilly.com/library/view/c-in-a/9781491924174/

As far as code examples, I find there's a lot of simple C graphics programs using the SDL2 library discussed on Youtube. Also simple ncurses programs are worth looking at. For example here's a video on making a tic-tac-toe game with pure C linked to github source code, just a few files:

https://www.youtube.com/watch?v=gCVMkKgs3uQ

https://github.com/tsoding/profun/tree/master/procedural

For practice, CodeWars has a lot of nice simple C challenges to work on.


I've been using GPT this way. "Write the header file for a function that does X." Now write the implementation. Does a great job when prompted with a header file.


Depends on your style of learning, but most people learn best by implementing something in a new language. Here are a few examples: a Brainfuck interpreter, a raytracer, even command line tools like ls, cat, grep are good exercises. If you are into electronics C is great for embedded work - I would buy a Raspberry Pi Pico and write C programs for it.

I would also suggest to enable all warnings your compiler allow for and sanitizers if possible. You will also want to learn to use a debugger that works on your operating system.


The language is only part of it. In my opinion, you would learn even more about C by consuming well-known libraries written in C and trying to do something useful with it and complementing that with some books, etc rather than just learning the syntax and semantics of C.

There are tons of useful/fun things you could do with C. Write some desktop apps with GTK, a web server with Mongoose (https://mongoose.ws), etc.


I'm a C# guy who learnt C over the past 2 years. It absolutely made me a better programmer. I learnt by going through K&R first and then Expert C programming by Peter van der Linden. I also went through OS books, books that talk about the machines like Understanding the machine. I program in many high level languages. The main difference I felt when learning C is, I felt like I needed to learn how the machine actually works (what happens when we run a program) to really appreciate C. I continue to pursue this learning, these days I'm looking into embedded stuff.

Also look at C programs. I study old, small unix programs like "more".

I must also say that I see people asking about learning C on sites like Stack Overflow and getting discouraged saying that it's outdated and all. These people are doing a great disservice.


As C# guy who had to work with C for a while - this language is minefield.

If you want to create your own language and want to experience what choices are subpar by modern standards - C is way to go.

If I had choice then I'd pick Rust anytime when messing with low level programming.

I don't understand fascination with C just because it's "tradition" "everywhere" or "gives you full control" - especially that, since it brought us countless security issues


You'll wish you have decent C experience whenever you need to call an OS API directly; or whenever you need to write your own bindings to a library written in C.

PInvoke requires a working knowledge of C's concepts; you need to know the basics about pointers and how data is represented in order to do it correctly.

This statement comes from a lot of personal experience: I wrote a (currently closed source) adapter to call into SWMM from C#. (https://www.openswmm.org/SWMM51007/swmm5-c). (Hopefully I can open-source it at some point.)

In https://www.syncplicity.com/en, I wrote code in C# to interface with a closed-source driver to create a user-mode virtual disk drive. I also integrated with a different Virtual disk drive product that was written in C++ via PInvoke. I used PInvoke to create bindings between C# and Objective C for the Mac version as well.


Maybe yes, but on the other hand I've never been paid for anything that used OS calls directly.

The only times I've used such APIs was creating simple keylogger for tests and very simple cheat for a video game (tested on non-official servers).

C# nowadays seems mostly like web backend development, tools, game scripting or automation, at least that's my perception.

Anyway even if WinAPI, then why not Rust?


> Anyway even if WinAPI, then why not Rust?

Plenty of reasons:

First of all, most operating systems (and other lower-level APIs) you want to work with expose their APIs as C. These don't all have bindings in Rust. Even if you want to do them in Rust, you need to know enough C to be able to understand how to consume the API.

But then, there's plenty of legacy code in C. We aren't going to rewrite everything in Rust overnight.

More importantly, I think the "jury's still out" if Rust is better than C for embedded programming; or programming that's primarily direct memory manipulation. (And, if your embedded environment only gives you an API in C, you need to know enough C to write the API bindings for Rust before you can do embedded programming in Rust.)

Personally, I don't have any experience with unsafe Rust code. (I only do hobby projects in Rust.) In C# you can do C-style direct memory manipulation if you need to; but I'm not sure if Rust's "unsafe" is equivalent.


> Anyway even if WinAPI, then why not Rust?

Because they said they already know rust and were asking about C…


I meant in general, not just OP


Are you me? I am learning C lately, been a few weeks. I am an SWE with 7 years of experience in JS/TS world.

Currently I am trying to learn how to test C correctly, seems there are lots of approaches.

It began when I decided to learn low level development a few months ago. I completed my Chip 8 emulator. Next I bought Arduino a month ago and I was playing around with it. Now I am reading AVR Programming book so I decided to learn C properly. On the side I already made a small keyboard with a microcontroller with QMK firmware. Soldering and stuffs.

Next what I’m trying to learn is some electronics knowledge just enough to make stuffs.

This is way more fun than my web development job!

Currently the resources I use: - Learn C The Hard Way - BeeJ’s guide to C - random video tutorials from the internet - Make: Arduino - Make: AVR programming


The K&R book is a great example of clear technical writing, but it's also quite terse. I'd recommend C Programming: A Modern Approach by K. N. King instead, as it uses a more gentle pedagogical approach.


> The K&R book is a great example of clear technical writing, but it's also quite terse.

That's not really a “but”; eschewing superfluous verbosity is a hallmark of good technical writing.

IMO, a more significant strike against K&R, which is excellent for its time, is that it is hopelessly dated—unless there is a third edition I am not aware of—providing, in the second edition, a preview of the first edition of ANSI C, which was standardized just after it was released.


I suggest downloading and playing with Raylib[1]. It's written in C, not C++, and is a library for video games, but it can be used to produce apps too. It has a ton of examples for you to review and modify as you learn, and it is cross platform. There are even bindings to other languages if you decide to leave C and use your favorite language. It's a one-click download and setup. Couldn't be easier and more fun!

[1] https://www.raylib.com/


SDL or Raylib are very good to quickly write interactive programs or simply play around with the samples.


C was the first language I learned after messing around with various flavors of BASIC way back in the day. I learned C using Turbo C for DOS and a big book, which is probably an 'obsolete' way of learning in 2023.

Haven't used it professionally in over a decade now, I'd be interested in learning Rust, but don't really have a need to do anything low(ish) level these days.


Same here! I started with AmigaBASIC and 68000 assembly and learned C when my family switched over to Intel/DOS machines.

Addressing modes back then!


Yep. Started with Apple BASIC on an Apple ][e, then Amos on the Amiga, then C on MSDOS :).


Learn C using the classical books, but also care about how to mitigate security issues while coding in C.

"Secure Coding in C and C++"

https://www.oreilly.com/library/view/secure-coding-in/978013...

"The CERT C Secure Coding Standard"

https://www.oreilly.com/library/view/the-cert-c/978032160319...

MISRA-C

https://www.misra.org.uk/

Frama-C

https://frama-c.com/

Also have a look at the static analysis and warnings available across all major C compilers.


I had the same itch for a long time. I eventually took the free Harvard CS50 course. Its the video lectures you can watch on demand. It gets into python at the end which I skipped as I already knew python.

I really enjoyed it and think the teacher is great. I don't think all of it is necessary if you are already a developer, but I didn't have a traditional education so it filled in a few gaps for me too.

https://learning.edx.org/course/course-v1:HarvardX+CS50+X/bl...


Excellent choice! I started off 2022 with learning c and it’s a lot of fun!

As some other commenters, I really recommend Modern C by Jens Gustedt.

If you’re on Linux you can use man pages for most or all of the c stdlib, it’s a really convenient way to check up on stuff directly from the terminal, less tempting to rabbit hole into something else while in a browser.

I started contributing to a really small open source project, it was less daunting than a large well written, well formatted project and you get to run into “accidents”, figure them out, fixing them, learning from the experience. I realise this is a matter of personal preference, for me it’s a nice learning experience.

Also having (or making) friends who knows c is really helpful.

Good luck!


This is the best reference site I've found: https://en.cppreference.com/w/c

There's also man pages for all the libc stuff. Try `man 2 listen` or `man 3 printf`.

The VSCode plugin for C is pretty decent as well, the Microsoft one called 'C/C++'.

I'd also recommend doing a readthrough of the GNU Make docs. They are succinct and full of useful stuff: https://www.gnu.org/software/make/manual/make.html


The suggested way to learn C in 2023 is the same as the suggested way to learn all languages for the past decade or so.

Do you like videos? Find videos on YouTube and watch them.

Do you like books? Go on Amazon and search for "C programming".

Do you like reading code? Go on GitHub and start reading the source for any project.

Or just find any online resource and use that.

The most important thing is to write code to do something you're interested in. If you're interested in solving puzzles, solve some puzzles. If you want to write a game, write a game.

Above all, you shouldn't waste time concerning yourself initially with what the "right" thing to do is. Do NOT let the perfect be the enemy of the good. It's OK to ignore the advice of anyone who tells you you need to be concerned with how to set up your project the right way, or tells you to avoid certain "dangerous" functions in the standard library. Just avoid all dogma.

Since you're learning, thinking about these things now is a huge waste of time. It's much better to write code that actually does things. If you thoroughly engage with this process, you will figure this stuff out on your own naturally. Or you won't, and then someone will correct you later, at which point you will be in a better position to appreciate their advice.

Biggest time-waster: reading this thread. These threads are mainly a venue for people with minimal experience to regurgitate things they have read elsewhere.


Arduino programming can be a pleasant intermediate step in learning C/C++. Specializing specially in C can be easier after that experience.


Read K&R. Yes, it's explicitly not modern C, but it enables you to think about C from a foundational level from which you can then go on to learn modern C. Build a project in C to learn how and why it works, and you'll understand how memory safe languages like Rust came about. This is what we did in college, started with C then moved on to Rust, it worked well.


What book would you suggest to someone who started with the K&R 2nd ed, then did other things, and now wants to catch up on the more modern C standards, at least the more widely supported ones?



The C Programming Language is a decent overview of the language. After that using it in a real project is the best way to learn. If you know Linux pretty well and know what syscalls are then you might be interested in reading the Linux source code and writing kernel modules (they're written in C). If none of that sounds familiar to you the overhead is probably too high for going that route to make sense.

In general, the reason to use C is because you are doing something that interfaces with the OS. But the problem with software at this level is that because the abstractions are so low level unless you understand something about the design/architecture of the software the code is really hard to understand.

So I would pick some project that is interesting to you and that you have some familiarity with already and try to implement a simple version of that in C. It is actually not too hard to write a WebSocket or HTTP server in C, so if you are familiar with web programming, writing one of those might be a fun project.


C is a very minimal language, you can learn it in a day if you are already familiar with C-like syntax. I would recommend using it on embedded systems, such as an Arduino (technically uses C++, but it's mostly hidden), so you can appreciate both the speed and minimal memory footprint and you would be abstracted from the complexity of operating systems.


If by learn you mean rote-memorize some syntax. I doubt most people who have never touched it will manage to use or even understand enough about pointers and arrays and stuff in a single day. Get some stuff to compile maybe, yeah.


I think a good place to start is to mostly ignore most/all the advice in this thread. I haven't obviously read every response but I have struggled to find any response near the top which isn't recommending something which will give poor results or is outright wrong.

Good resources:

- #c on libera.chat *

- https://www.iso-9899.info/

Good books:

- C Programming: A Modern Approach - K. N. King

- K&R2 with the errata at hand and the guidance of someone experienced when doing all the exercises

Good advice:

- Don't write a single line for which you are not sure that the behaviour is either well defined by the standard or by your particular implementation (and if the latter is the case, ensure you are well aware of the implications and document them appropriately).

- C is not a "try it and see" language, trying it will lead to undefined behavior and buggy code which you might not even become aware of until you have "learned" the language.

- Lots of C out there is littered with poor practices or heavily specialised to the task/target set of architectures/situation and is therefore not a good example for learning. Feel free to read lots of C once you have the fundamentals down, not before.

Things to avoid:

- Every online tutorial (no I haven't seen them all but none of the popular ones seem to instill the right discipline and are usually full of errors, one of the ones linked from this thread has a bug in the hello world program in the first exercise).

- Most books on the matter.

- Writing C.

* disclaimer: I am one of the founders of this channel.


If you are learning for historical context and curiosity reasons, K&R is a good place to start. It's short easy to ready but is missing a lot of important context. A lot has changed in the world since it was released.

If you are learning for practical reasons, like you have a project in mind, then it will be dependent on that project. C patterns and idioms vary a lot per project and time period. For a newer, more practical book I liked C Programming: A Modern Approach. Just don't go into it not expecting it to be too modern. The subject matter is still still C. After that you'll still probably have a lot to learn for whatever project you have in mind. C has a lot of quirks, peculiarities and shortcomings. There is no standard way of dealing with them so each project has their own best practices or set of helper APIs/tools with some minimal overlap.


I’d also recommend reading The Linux Programming Interface [1] as an alternative. While it describes the Linux API, it does so through tons of examples in C, so you can see how things are actually done in C-land.

[1] https://man7.org/tlpi/


I learned a lot getting an Arduino and building stuff with it in C. With zero C and zero Arduino experience I wired together an e-ink display, SD card reader, and some buttons to build a basic e-reader.

I would have never been bothered to build something in C in an environment where I can reach for any higher level language.


The Arduino ecosystem is heavily dependent on C++.


As a C/C++ dev, I want to learn Java. With its huge and sophisticated ecosystem, platform independence, the safety of the language, good efficiency, it almost sounds like one must be insane not to use it these days... (Sorry for being off-topic here.)


You'd be better off learning C# since it learned from Java's mistakes.


I program in C professionally. It's a good language to learn how processors actually work. It's on the embedded side, where there are other options but either they're not mature (Rust) or were never really taken up (Ada). Embedded C it's just you and the hardware. It's a good way to learn about what's actually going on. Anything, like an Arduino or Arm cortex is great. Small warning about ESP32 boards - some are based on the Extensa cores, which means you need to use their compilers. Others are based on Risc V - do your research.


I am fond of Notes on Data Structures and Programming Techniques by James Aspnes: https://cs.yale.edu/homes/aspnes/classes/223/notes.html it has a short and sweet overview of C as well as a sections on problems with C. Another useful resource is Libc's info manual (in Emacs: C-h i m Libc<return>), it's a well-formatted, clear reference.



maybe try some embedded development, like raspberry, light up some leds. Embedded development is fun, educational and one of the last bastions of programming where C makes sense.


ESP32 is quite nice. It is much lower level than Raspberry Pi or similar SBCs, and C really makes sense there.

It ships with pretty high-level libraries (connecting to a Wi-Fi network is ~200 lines of C code), and you'll be running on top of a small operating system (FreeRTOS). But you still have full access to hardware and all the fun of working directly with it. The dev boards are quite cheap at $3-4 per piece, and have lots of peripherals (including Wi-Fi and Bluetooth).

Have a look for ESP-WROOM-32D at aliexpress, or whatever the platform of choice in your country is. Some of the newer boards are built on RISC-V, if that's your thing.

Their SDK also has first-class Linux support (and the other two OSs, obviously).

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/


I suspect they meant the Pico/RP2040.

Depending upon their goals, something like at ATmega may be a better choice. ESP32 and RP2040 development places a lot of emphasis on using libraries. That's fine, but it doesn't really highlight how C is different from most other languages. In contrast, there is a lot of information on low level programming for the ATmega. The RP2040 would be my second choice. I believe the libraries are entirely open source, which means you can read the datasheet and can reference the library source to see how something is implemented in C.

Granted, the ESP32 is a lot more fun if the intent is to build something.


K&R book. Nothing come close although it lacks on modern C.


Well, GNU/linux is more "C plus GCC" than pure C. There are a lot of fancy things that GCC gives you that you'd otherwise have to do explicitly.


C has the unique distinction of being criticized on the one hand for the complexities of vendor-specific extensions and portability concerns... and on the other for being insufficiently like Rust or Go, which are defined entirely by their proprietary implementations.

I don't think I've ever seen this criticism leveled elsewhere. Do people criticize JavaScript programming because the ECMAScript standard doesn't give you everything you could want?


There is no meaningful sense in which either Rust or Go’s reference compilers is “proprietary.” If you’re trying to say that there is no ISO standard for the two, that’s an entirely different problem (and one shared by the overwhelming majority of programming languages).


> There is no meaningful sense in which either Rust or Go’s reference compilers is “proprietary.”

Nobody is talking about the compilers. This, right here — the fact that you are conflating a language and one implementation — is the whole point and is indicative of the tight control the respective organizations keep over their languages.

The direction of the languages is entirely up to their private owners, and that exclusivity is enforced via intellectual property law. They are exactly as proprietary as RHEL or Unix.


This is not a definition of "proprietary" used anywhere in the open source community. Private direction (which Rust notably does not have) does not somehow erase the fact that both are permissively licensed and have open codebases that you can use and contribute to to your heart's content.

I don't even know what you're referring to with IP law. The projects' names and logos?


> I don't even know what you're referring to with IP law. The projects' names and logos?

I think it's the fact that if you took the Rust codebase and forked[1] it to accept new keywords, the resulting language that it accepts is most definitely not Rust.

If you did the same to a C compiler[2], the resulting compiler would still be called a C compiler by everyone.

[1] Assuming that the license allows it.

[2] One who's licence allowed this.


Yes, the license allows it. Rust's compiler is more permissively licensed than GCC, and is roughly as permissively licensed as LLVM.

This argument does not make sense: if you fork GCC or LLVM and change the language frontend for C, the thing you are parsing is no longer standard C. This is exactly the same as is true for Rust, except that the reference is the the living standard rather than an ISO standard.

By the original commenter's logic, the modified C compiler would effectively be proprietary: it no longer has a public, liberally licensed specification that it conforms to. But this isn't the way anybody in the open source community uses the word "proprietary," because it precludes any open-source work that doesn't have a corresponding formal specification.


> This argument does not make sense: if you fork GCC or LLVM and change the language frontend for C, the thing you are parsing is no longer standard C.

It doesn't make sense to you, certainly.

To the type of person who've used a dozen different C compilers, all of them containing extensions to the language, and all of them still advertised as "C compilers", the argument makes perfect sense.

I mean, the input to the GCC C compiler is, by default, C with extensions, and yet even you still called it a C frontend, not a "SomeOtherLanguage" frontend.

You may not agree that the argument is valid or sound, but you can't with a straight face say that it is an unreasonable position to take.


> You may not agree that the argument is valid or sound, but you can't with a straight face say that it is an unreasonable position to take.

That's not the argument I'm advancing: I'm saying it does not make sense to call that modified C compiler "proprietary."

I don't care if you call it "C" or not, because everybody who writes C understands that compiler-specific extensions are commonplace. But the existence of non-formally-specified extensions doesn't somehow override the permissively licensed nature of the compiler.

Similarly, going back to the original argument: it does not make sense to call Rust "proprietary" because it only has a living specification, rather than a formal one. It's permissively licensed, and you can modify it to your heart's content. The only reason people wouldn't call your changes "Rust" is because the community doesn't share the same expectations re: vendor extensions that C's community does.


> it does not make sense to call Rust "proprietary" because it only has a living specification,

It doesn't have a "living specification", it has a reference implementation. There's a difference. HTML is a living specification without a reference implementation. Rust (and many other languages) have a reference implementation without a living specification.

> The only reason people wouldn't call your changes "Rust" is because the community doesn't share the same expectations

That's not true; you cannot call it Rust because Rust, the programming language, is trademarked.

It is protected, you understand? There are legal barriers to calling your NewLanguage "Rust", as explained by the foundation themselves over here: https://foundation.rust-lang.org/policies/logo-policy-and-me...

Writing your own language and calling it Rust is legally forbidden.[1] You are, of course, free to use the permissive copyright but the name is trademarked.

Now, with C, OTOH, as an ISO standard it has no trademark so this argument does not even arise.

[1] As far as I can tell, it would be legally forbidden even if your new implementation of Rust behaves identical to the reference implementation. The best you can do is call it Rust compatible.


There is a difference between open software and open standards. The two are orthogonal. Open software can use closed standards (though must usually reverse-engineer them); closed software can use open standards. See, e.g., LibreOffice support for .doc files; Microsoft's TCP/IP stack. Please make an attempt to engage with intellectual honesty, and stop intentionally conflating the two.

The issue at bar is whether Rust the language is proprietary, especially as compared to C. Something is proprietary within the standard meaning of the term if it "is used, produced, or marketed under exclusive legal right of the inventor or maker." Merriam Webster, Online Edition, available at https://www.merriam-webster.com/dictionary/proprietary.

In this case, The Rust Foundation maintains and exercises exclusive legal rights over Rust that nobody exercises over C. If I make a C compiler with extensions, I can still call it C and I can still participate in C governance. C is an open standard. See https://www.open-std.org/. However, the same is not true for Rust, where governance happens entirely under the auspices of one vendor, who uses trademark law to ensure that no competitors can exist without its explicit approval. Specifically, any Rust variants other than those required for porting require explicit written permission. See https://foundation.rust-lang.org/policies/logo-policy-and-me.... Furthermore, even if I accepted my impotence in the governance process and even if I resolved to call my Rust variant something else (FeO?), competition in the market would still be chilled by The Rust Foundation's refusal to commit to fair, reasonable, and non-discriminatory (FRAND) licensing (something that is required as part of the ISO standardization process). If a competitor ever did arise, patenting the borrow checker mechanism would be all it would take to completely crush them.

I am glad that rustc is open source. I am glad that The Rust Foundation is a non-profit. I accept on faith that they want to do the right thing. However, they have deliberately created a monoculture that they enforce through IP law. Rust is proprietary, i.e., it is "something that is used, produced, or marketed under exclusive legal right of the inventor or maker." There are no open standards, there is no FRAND licensing obligation, there is no allowance for any Rust variants other than those explicitly permitted by the primary vendor of Rust compilers.

You brought up Python before, which is appropriate: Python explicitly is a "benevolent dictator for life" language. The difference with Rust is that the dictator is a legal personhood instead of a single living, breathing person. But dictatorships, even benevolent and well-intentioned ones, are ill-suited to the requirements of stability and predictability that are so vital to systems programming.

Imagine, God forbid, that The Rust Foundation goes defunct at some point in the next 100 years, and its IP bought up by the next generation's SCO or Novell or whatever, and they decide to patent the borrow checker and whatever other innovations are in Rust. Do you think that would be a bad thing?

Because it can only be bad if you agree that Rust is proprietary. If Rust were an open standard (including the borrow checker as part of the standardized compilation process and subject to mandatory FRAND licensing), then that outcome would be mitigated against.


This is a very large comment, filled with legitimate observations about how Rust (and most other programming language communities) choose to defend their name, logo, etc.

It has absolutely nothing to do with how "proprietary" is used in the open source community. To make it as simple as possible: if your use of the word "proprietary" includes Python and Rust but excludes Borland C, you've failed to use to word in a way that is substantive and useful to everyone else in this community.

The implied risk of Rust's trademark terms is entirely ahistorical: C did not win as a systems programming language because it satisfied FRAND or any other standard for openness. It won because Worse Is Better, in spite of onerous licensing restrictions by companies with extremely expensive and proprietary C compilers.


>It won because Worse Is Better

I don't think this is why. I think it "won" because it was the best "high-level" language of the time and exploded to fill a huge niche, historically. In other words, historical luck.

I think that's also how JavaScript won.

Since it's always luck, and since the luckiest thing is rarely the "best" thing, it just looks like it's a selection for ironically worse quality from the outside.


"Worse is Better" isn't meant to be derogatory: it's the term of art used by the Unix world to describe Unix and C's own adoption arc[1].

[1]: https://cs.stanford.edu/people/eroberts/cs201/projects/2010-...


> Imagine, God forbid, that The Rust Foundation goes defunct at some point in the next 100 years, and its IP bought up by the next generation's SCO or Novell or whatever, and they decide to patent the borrow checker and whatever other innovations are in Rust. Do you think that would be a bad thing?

1) I'm not certain the Rust Foundation actually owns the underlying patent IP for the borrow checker.

2) But granting it does, imagine, the foundation or its successors files for a patent years after including that IP in Rust and years after granting two extremely permissive licenses (MIT/Apache 2) for the use of that IP, and tries to enforce their patent rights against your fork, FeO.

3) What exactly is their hope of winning a patent infringement case after granting those extremely permissive licenses?

Don't both MIT and Apache 2 provide a very strong defense against infringement where one is using and modifying the Rust code base (you fork creating FeO)? If you don't like Apache 2's explicit patent grant, Rust of course offers you the option to use MIT's implied grant.

"Any language used by the owner of the patent, or any conduct on his part exhibited to another from which that other may properly infer that the owner consents to his use of the patent in making or using it, or selling it, upon which the other acts, constitutes a license and a defense to an action for a tort." De Forest Radio Telephone Co. v. United States, 273 US 236, 241 (1927).

Can you show me an instance where anything like what you describe has occurred? If not, you should describe precisely how your hypothetical could occur? Because, from where I sit, your theories seem like pure FUD.


> If a competitor ever did arise, patenting the borrow checker mechanism would be all it would take to completely crush them.

Apache 2 includes a patent grant? So I think most of this comment is clearly erroneous.


> both are permissively licensed

No, the code of the implementation is permissively licensed.

Do I really have to explain, on HN of all places, the importance of distinguishing between implementation and interface?


This is incorrect on multiple levels: there is no organization that has "exclusive" control over Go, much less Rust. There's a company (Google) that made Go, but they have no control over the source code itself beyond the terms of the non-proprietary license they provide it under[1]. Even the things that Google does w/r/t Go are not even remotely controversial in the context of the definition of proprietary software, like CLAs. Linux has a CLA!

Comparing this to Borland or Microsoft is bizarre: Microsoft and Borland actually do have proprietary C compilers that they do not make publicly available in source code form. Those compilers in turn have all kinds of non-standard, proprietary extensions.

The one thing that sets C apart from Rust and Go is the presence of an official ISO standard. But this isn't material to the definition of "proprietary" in the open source world. And, well, that ISO standard is itself copyrighted.

[1]: https://github.com/golang/go/blob/master/LICENSE

Edit: You shouldn't delete and re-write your comments. Here's the original comment I responded to:

> That's a dubious claim, and irrelevant besides. They are proprietary, in the standard meaning of the word, because a single private organization has exclusive control over each, but whatever word you choose to describe that is up to you.

> Google owns Go in a way that has never been true of Microsoft (or Borland or GNU or Apple...) when it comes to C.

Edit 2: For the edited comment: you're setting up a distinction that does not matter for programming languages that do not have formal specifications. There is no "interface" to distinguish against, and the claim that Rust (or Go, or Python, or any other language without an ISO spec) is tacitly reserving all rights to the design of the language itself is completely unsubstantiated.


Your position that not having a standard is irrelevant for languages that don't have a standard is circular and bizarre.

The fact that you keep focusing on whether compilers are proprietary instead of whether Rust and Go are proprietary is starting to seem deliberately evasive. You're free to extol the virtues of open source software, and I agree with you, but it's utterly beside the point.

.rs is analogous to .doc. The "right" way to handle it is defined solely with respect to the reference implementation. I view that as a problem. You may disagree, and that's fine, but don't pretend this is a conversation about something else.


> The fact that you keep focusing on whether compilers are proprietary instead of whether Rust and Go are proprietary is starting to seem deliberately evasive.

"You keep using that word. It don't think you know what it means." -- Inigo Montoya

This is just bizarre. If MIT/Apache-licensed Rust is proprietary, then anything could be? AFAIK there is no POSIX definition for epoll/io_uring. I suppose epoll is proprietary too?

proprietary: "2: something that is used, produced, or marketed under exclusive legal right of the inventor or maker"

Can Rust be forked, modified, used/sold and distributed with your changes? If yes that hardly seems like an exclusive legal right. Your problem seems to be that people trust the Rust project, and don't trust you or a central committee (yet). But that doesn't make a project proprietary. It makes it implementation defined, which has its own problems, but those are not the same problems of as those of proprietary software.


> MIT/Apache-licensed Rust

Rust is not MIT/Apache-licensed, rustc is.

Rust is licensed under terms that require explicit permission for use outside of a few very narrowly-defined circumstances.


> Rust is licensed under terms that require explicit permission for use outside of a few very narrowly-defined circumstances.

I think you mean the Rust trademark, and sorry, but you don't get to use IBM or Google's mark willy-nilly either? I'm not sure it's a realistic expectation on your part to be able to market your changes under the other guy's mark.


Where's the circularity? This is the claim: you can't claim that a nonexistent thing is proprietary. Rust and Go do not (to my knowledge) have any sort of standard other than the living standard of the reference implementation, which is itself not proprietary. Anybody is welcome to copy or modify that living standard, per the terms of the permissive license.

This is the overwhelmingly common state of affairs for programming languages: Python, PHP, Go, Rust, etc. do not have formal standards in the sense of C, but instead of a living standard in the form of their reference implementation. The reference implementation is permissively licensed, so the "standard," insofar as it can be said to exist, is also permissively licensed.

Edit: Again: this is just not what the definition of "proprietary" is, in the context of open source. There is a legitimate grievance that you're expressing about software standards and implementation diversity, but it has absolutely no bearing on whether the reference implementation is proprietary or not.

By analogy: I, an open source developer, create a new file format $FOO and release my reference implementation of a $FOO parser under a permissive software license. Am I somehow compelled to spend time writing a formal specification of $FOO to make it non-proprietary? It might be nice for me to do, and nothing stops anybody else from converting my living standard into a formal one, but I am absolutely not compelled to do it.


All commits to the Go repository must be approved by two Google employees: https://groups.google.com/g/golang-dev/c/K7oGURi0wTM/m/3mg1O...


Yes. Again, Google can do whatever it likes with its repositories. This is entirely unrelated to whether or not the software is proprietary.

Compare Google's practices here to Qt's[1], CMake's[2], or any other large open source project that is primarily maintained by a single company.

To be abundantly clear: I don't think this is a good way to run an open source project, but it is a legitimate way to run one. So long as the source code and standards (insofar as they exist) are themselves permissive, then the community details are just that.

[1]: https://wiki.qt.io/Qt_Contribution_Guidelines

[2]: https://github.com/Kitware/CMake/blob/master/CONTRIBUTING.rs...


> The direction of the languages is entirely up to their private owners, and that exclusivity is enforced via intellectual property law.

Can't you just fork the language, or, just re Rust, participate in the RFC process? Do we need more bureaucracy?


yes


True. The author might enjoy studying something like OpenBSD (https://github.com/openbsd/src)


"GNU C" has a number of features that make the language far more pleasant if you're willing to give up the portability and use them. A big one if you've been using modern languages is anonymous functions.


It’s worth noting that GNU C uses trampolines to implement their “nested functions” extension, which in turn requires an executable stack.

In other words, using that extension silently disables one of the most basic and effective security mitigations we have for C.


The C programming language book.


Just like C, there is a stark beauty to the original K&R C Programming Language book. And there's an admirable clarity in the writing that has set the standard for all language manuals that have followed. It is, indeed, a terrific read. As long as you're not trying to learn C.

It's really out of date. It doesn't cover subsequent C standards; and it doesn't cover any of the best practices that have subsequently evolved to protect us from the things in C that are deeply awful (in retrospect) in the original. Or any of the evolved practical lore for writing good, portable, safe C code.


> As long as you're not trying to learn C.

That's insane. K&R (2nd ed.) can easily be the only book you want to work through if you want to learn the basics of C.


Since you are already familiar with other languages, I suggest just pick a tool that you use daily that is open source in C, and start hacking it.


When I was learning C, I found most books only skimmed pointers, a topic I was having a hard time with. Reek's Pointers on C is a beginner C book in that it goes over all the novice stuff, but it has a concentrated focus on getting you to understand pointers. I recommend it.


It seems to me that the main reason to learn C would be to be able to dive deeper into the low-level implementation details of some hardware platform.

With that in mind, I would suggest picking a piece of hardware you want to learn more about, and using C programming to see what makes it tick.


No doubt the best book on the subject of modern C

https://www.amazon.com/21st-Century-Tips-New-School/dp/14919...


There's was a great article on HN on how C is more than a programming language. It is a protocol for most of computing. I would suggest you to look into the actual influence of C on computing and protocols instead of just looking at software.


I suggest learning C for two non-usual reasons:

1. You study the wonderful Kerninghan & Richie book. It's a great work of art.

2. C's architecture is just raw computing. Try building a toy interpreter or compiler and you will know most of CS in bargain too!

Good luck my friend.


K&R probably taught more working C programmers than anything besides experience.


I'm not a C programmer, but I have a program written in C that I've adopted. So I to am interested in learning modern C. Is there a text that gives the current recommended techniques for C23?


Note that [IMO] one of the main values of learning C in 2023 is that it's small and simple enough to learn the precise semantics of almost all of its parts.


The 2018 ISO standard [1] is 520 pages. Not what I would consider small. Nor is it simple. The integer promotion rules and undefined behaviours will trip up even experienced C programmers.

Something like R5RS for Scheme (50 pages or so) is what I think of when I hear small and simple.

[1] https://www.iso.org/standard/74528.html


I’d probably start with learning assembly. C maps to assembly very well, and you could understand a lot of what’s happening under the hood this way.


Great language to learn data structures and algorithms. If you still like the language itself after going through a course like that, awesome.


Learn the PDP-11 assembly first, and then you will understand many design decisions made in C (especially behind pointer arithmetics).


I am finding that I do well with Udemy courses first and then find the books I need and docs that will fill out the holes.


Does anyone have a good recommendation on developing operating systems?


This depends on how deep you want to go. I honestly recommend starting small.

First, Code by Petzold to make sure you understand how a computer truly works. Then I recommend:

Understanding Microprocessors (Motorola)

8086/8088 Assembly Language Programming

Dissecting DOS

Practical Filesystem Design

FreeBSD Internals

The reason there are so many books is because it’s a big topic. The reason most are old is that things were once much simpler. Modern stuff builds on old, so if you get a good understanding of older stuff, you have an idea of what is happening. From there, I strongly recommend getting a good understanding of UEFI. UEFI will handle most of your system initialization no boot requirements, allowing you to focus on higher level stuff. Prior knowledge of systems will still be a requirement so that you can understand some of the assumptions and choices that UEFI makes.

OSDev is fun. I hope you have a good time.


Great recommendations; a couple i had not come across.

>Understanding Microprocessors (Motorola)

>Dissecting DOS

Can you share or point me to where i can get the above from?


For Dissecting DOS, I recommend eBay, but it is available on Amazon:

https://www.amazon.com/Dissecting-DOS-Code-Level-Operating-S...

The original companion floppy for that is available on archive.org:

https://archive.org/details/dissecting-dos-companion-floppy-...

Understanding Microprocessors is a small book, and currently unavailable anywhere I've seen except for eBay, but it's also normally quite inexpensive.


The C Programming Language by Brian K is still the best resource.


[flagged]


chatgpt detected ;)


ChatGPT.


If you've learned Rust then you've learned a lot about the importance of ownership and lifetimes, something C will never teach you directly. It will only punish you for failing to understand.


How in the world in this day and age of nearly infinite resources to learn ANYTHING on the internet is this a question that gets voted up to the top of HN?

Here's an idea: pick a project that interests you and start. For any question or issue you run into, there will be 1000 Youtube videos to choose from, and 10000 online tutorials. There will be an associated sub reddit to ask questions.


> How in the world in this day and age of nearly infinite resources to learn ANYTHING on the internet is this a question that gets voted up to the top of HN?

I'd guess it is because Sturgeon's Law[1] applies to most things on the internet. In fact there is so much crap when it specifically comes to instructional material on the internet that it reaches a point where we find that Sturgeon's Law was only a linear approximation to crappiness that is only valid with the relatively limited crap levels they were capable of producing 60 years ago when Sturgeon's Law was formulated.

The internet is capable of achieving crap harmonics, and we find that something like 90% of the stuff that doesn't seem to be crap is actually crap too.

The HN answers to this question are going to have a much lower crap level which will keep them well within the linear region of the Law. Many here recognize that having someplace that answers this question with only a 90% crap level is good and so upvote it.

[1] 90% of everything is crap


I like firearms as an analogy here.

Rust is like a modern rifle, unloaded, with six safeties and three locked triggers in a gun safe. The ammunition will harmlessly self-destruct if you don’t focus properly before firing.

C is sort of like Rust except the rifle is on the couch, loaded, one in the chamber, all the safeties are off, the numerous open triggers are held by RNGs, and the business end is pointed right at your most prized possession.

It is fun, in a way. Use it in an environment that you don’t care too much about.


Ha.

Confession time: I came to this thread to Ctrl-F for "Rust" to find the Rust-C fisticuffs. And this answer is like what I would expect if I said "ChatGPT, write me a reddit-style Rust defense that would rustle some jimmies."

I'm about equally capable at both Rust and C - I could pass a 1st year undergrad CS course using either, but I'm no better than that.

I know C has its place - its marketshare of embedded devices and gamedev is huuuge - and Rust... may eventually reach a similar place of importance, but isn't there yet.

I also know the very best C and Rust devs are pretty much geniuses - Ph.D. level understanding of math, that kind of thing - and would squash me in any type of fair competition.

Maybe in the year 2050, an attitude of condescending acceptance towards C might be appropriate. And also... maybe not, because C might not slip. Who knows?

And really, beyond this pretty crude but accurate-ish description, I think we're getting into unnecessary hair-splitting, among people who don't work with either and wouldn't understand the tradeoffs anyway.


There is a lot of nuance in this discussion that someone inexperienced could misinterpret, you’re definitely right about that.


Meh. People love to hate on C but the invariants you have to keep track of are relatively simple (things like 0<=i<L.) Most languages replace these with multi-dimensional string based hashmaps that have much more complex invariants to keep track of and similar consequences for failing to do so.

Some languages like Rust and Haskell do a little better by having the compiler keep track of most of them (if you use it right) but the consequence of misunderstanding them here is accidentally coding yourself into a corner which is extremely unpleasant.

There are other things people like to talk about like automatic memory management and package management and again I'm not convinced these really improve much. The pain of allocating memory in C means people often find ways to avoid doing it altogether which results in much more predictable behavior. Same with pulling in third party libraries. It's rare using more than a couple is actually beneficial but when the package manager is there the temptation is way too much for most people and the result is both unpleasant and very vulnerable to supply chain attacks.

I'm still not convinced any of this is the improvement people think it is.


I mean I’ve worked with C for a long time. It’s love-hate. I think it’s hard to see the value from the other side of having internalized C, and Rust definitely encumbers you.

The number of things a beginner doesn’t have to know or worry about to code something as essential as a function that reads a file, searches for a string, and interacts in a serious way with the network in Rust vs C is substantial.

Probably I’ll get downvoted again but it’s fine.


But you do learn from such things (opening a file, reading from the network). All the stuff that can go wrong, and that it all has to be handled. Like writing a device driver.

It’s useful to write that C code, and then try to break it (e.g., to force a segfault rather than a proper error-then-exit).

Is knowing all that necessary? No, as you are kind of implying. ;-)


> the invariants you have to keep track of are relatively simple (things like 0<=i<L.)

If maintaining these invariants were so simple, why would the smartest people in the industry have so much trouble doing so? Humans cannot consistently write correct C, not even the ones who believe they can. We have decades of evidence.

> Most languages replace these with multi-dimensional string based hashmaps that have much more complex invariants to keep track of and similar consequences for failing to do so.

This take reflects a profound ignorance of the relative severity of different kinds of software defect.

When you get an array bound wrong in Java or Rust, you get an exception or a panic. Your program exits and restarts. You get a ticket for fixing the bug. Life goes on.

When you get an array bound wrong in C, you open the door for a nefarious actor to gain control over everything that your program can access.

These aren't similar consequences. They're not even on the same planet of consequences. C apologists are like apologists for asbestos and lead paint.


> Humans cannot consistently write correct C,

So? Humans cannot consistently write correct code in any language.

> When you get an array bound wrong in C, you open the door for a nefarious actor to gain control over everything that your program can access.

What's really interesting to me is how Heartbleed (the largest example of getting an array bound wrong) was orders of magnitude less expensive to fix than Log4j, and yet it was Log4j that resulted in gauranteed RCE, not Heartbleed.

> C apologists are like apologists for asbestos and lead paint.

Let's not go spilling hyperbole all down our shirt.

I get the feeling that a lot of people comparing C to things that kill have never worked in life-critical situations, the systems of which ran C for decades and decades, and never appeared to have lost very many lives in the process.

Military, munitions, healthcare machines ... I can't remember any of them losing lives because of a misfeature in the C programming language, and yet there you are, proudly proclaiming to the word that C is like Asbestos, which has taken peoples lives.

Get a grip.


My point is that they can't consistently write correct software in any language. Javascript for example has similar issues where if you're not careful about which keys in a hashmap you write to you can create situations that allow for all kinds of things including arbitrary code execution.

Modern C compilers/runtimes also have bounds checking (although I've never used it) like java if you want to use it.

Sure there's some improvement but it's not nearly as extreme as it's made out to be.


It's true that humans will inevitably produce software with defects. There are differences in the impacts of these defects.

> Javascript for example has similar issues where if you're not careful about which keys in a hashmap you write to you can create situations that allow for all kinds of things including arbitrary code execution.

Not without eval() you can't.

> Modern C compilers/runtimes also have bounds checking

No, they don't. There are C-like languages (e.g. C++/CLI) that do, and you can use containers, but no, plain C cannot do bounds checking. There's no room in the ABI for it, at least not without CHERI or ASAN.

> although I've never used it

One of the most dangerous things in the world is giving powerful tools to people who don't know that they shouldn't use them.


> My point is that they can’t consistently write correct software in any language. Javascript for example

I don’t think Javascript is the counterexample you want to use as a good language. It is like C where safety is traded for flexibility.

If people can’t write correct software in any language, the language designers can help, which is exactly what the Rust designers did.

It’s not great for everyone because now all the scar tissue that great C devs have around what near-fatal errors they’ve made previously has lost some of its value.


This analogy is really more like dogmatic Rustacean-ism than actual truth. Rust has it's merits. However, it's a tired language. It doesn't maintain very good stability due to it's ever-evolving compiler which makes it almost unusable in anything but a "move fast and break things" environment. It's too particular, making development a burden and interrupting flow. Most importantly, the community is absolutely exhausting to listen to and this post is a perfect example.

C can be dangerous, yes. No one is denying that. C is also extremely stable, fast, and a "known-known". With proper discipline that any experienced developer of ANY language will have C can be very safe. Most, if not all, dangerous errors can be found and fixed simply by understanding how to use valgrind. With the advent of modern CI/CD it's never been easier to remember to valgrind your code.

C is probably the first language I would use in an environment I cared a lot about. For example, if binary size, availability of libraries, competency of programmer, etc would be in my list of concerns I would use C. I take particular offense to the "RNG" part of your analogy. C errors are not random at all. They are always the developer's fault and are often very predictable (use-after-free, poor array hygiene, etc). Despite the ever-evolving condition of post-C religions (Go, Rust, etc) there are only a handful of languages that fit the bill for a so-called serious systems project. C, C++, Java, and C#. You simply will not find a better library ecosystem and community of highly tenured developers to draw from for at least another decade in other languages.


I don’t even prefer Rust to C personally, and I’m not a dogmatic sort. My analogy wasn’t particularly complimentary to either language.

If some people are too sensitive to take a little caricaturization of C in stride, maybe those people should examine those sensitivities.

Edit because I didn’t read your comment all the way through: uninitialized memory is RNG, functionally.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: