HACKER Q&A
📣 0x008

Learn C in 2023?


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.


  👤 suprjami Accepted Answer ✓
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


👤 andreygrehov
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!


👤 jerf
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.


👤 liendolucas
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.

👤 thom
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.


👤 gwbas1c
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.


👤 Waterluvian
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!


👤 jshrake
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.

👤 dxbydt
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.


👤 photochemsyn
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.


👤 AlexeyBrin
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.


👤 jviotti
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.


👤 kovac
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.


👤 gptadmirer
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


👤 pkkm
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.

👤 eggy
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/


👤 jcadam
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.


👤 pjmlp
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.


👤 adamrt
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...


👤 blaerk
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!


👤 grose
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


👤 sfpotter
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.


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

👤 satvikpendem
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.

👤 jeffreyrogers
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.


👤 dariosalvi78
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.

👤 Arch-TK
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.


👤 stusmall
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.


👤 Zanfa
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/


👤 hombre_fatal
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.


👤 Koshkin
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.)

👤 phoehne
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.

👤 tmtvl
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), it's a well-formatted, clear reference.


👤 iExploder
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.

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

👤 phendrenad2
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.

👤 Tarucho
The C programming language book.

👤 hzhou321
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.

👤 cptnapalm
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.

👤 aWidebrant
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.


👤 sumosudo
No doubt the best book on the subject of modern C

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


👤 selfhifive
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.

👤 hasitseth
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.


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

👤 mikewarot
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?

👤 pjdesno
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.

👤 p1esk
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.

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

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

👤 lucidguppy
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.

👤 jay754
Does anyone have a good recommendation on developing operating systems?

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

👤 astrodust
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.

👤 slingnow
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.


👤 svnt
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.