15 ms·
Ask HN: How do I learn C properly?
I have 15+ years of experience in many languages: javascript, python, go, etc.
I can write C, but I'm not confident I'm doing it the right way. There are now decades of forums and blogs I can search through, but I'd love to have a single, clean, clear source of truth for recommendations on how to write C code.
I've started reading "Modern C" by Jens Gustedt. I'm not sure if this is the closest to a modern source of truth.
Note, I'd like my C code to work on Windows, which possibly restricts the "right way" to features provided by C89. But again, I'm not sure, the internet is super clear on this.
Thanks for the tips!
- aWidebrant 7y agoThe main thing that C provides over other languages is direct hardware access. So study the hardware, find out what you want to do with it, then use C to implement it.
- Paperweight 7y agoPerhaps better than a book, can anyone authoritatively point to a few small-and-readable but best-in-class open-source C projects to use as a reference?
- mlvljr 7y agoSqlite
- diego_moita 7y agoLua and Sqlite sources are excellent.
- kick 7y ago* tweetnacl.cr.yp.to Crypto library in the size of a hundred tweets [ https://twitter.com/tweetnacl https://twitter.com/tweetnacl ] by the only person with a genuine claim to being able to write safe C & company. * https://github.com/mit-pdos/xv6-public https://github.com/mit-pdos/xv6-public & * https://github.com/mit-pdos/xv6-riscv https://github.com/mit-pdos/xv6-riscv UNIX v6 clone in ANSI C by influential Plan 9-era Bell Laboratories employee and now influential Google employee Russ Cox, along with influential computer virus author and son of one of the original UNIX authors Robert T. Morrison; entire source code fits in under a hundred pages of well-typeset documents [ warning, old copy, you should generate a modern one: https://pdos.csail.mit.edu/6.828/2011/xv6/xv6-rev6.pdf https://pdos.csail.mit.edu/6.828/2011/xv6/xv6-rev6.pdf ].
- DyslexicAtheist 7y agonot recent projects but everything that DJB implemented is absolutely elegant, low on bugs and great as a lesson for how to write secure C. e.g. qmail, djbdns, daemontools, there is a lot of ideas there you can learn from: https://cr.yp.to/ https://cr.yp.to/ It also helps to build up (and refactor) your toolset over time, memory handling wrappers, logging, I/O, daemonize (https://github.com/jirihnidek/daemon https://github.com/jirihnidek/daemon) etc, so that you don't have to keep reinventing the wheel. if I'd recommend one book then it's: https://en.wikipedia.org/wiki/Advanced_Programming_in_the_Unix_Environment https://en.wikipedia.org/wiki/Advanced_Programming_in_the_Un...
- vyskocilm 7y agoAny C based project of zeromq project like https://github.com/zeromq/czmq https://github.com/zeromq/czmq is worth to read. Pieter Hintjens started a book explaining all the design decisions there https://hintjens.gitbooks.io/scalable-c/ https://hintjens.gitbooks.io/scalable-c/ Sadly he didn't have a time to finish the book.
- 2OEH8eoCRo0 7y agoOldie but goodie: https://github.com/id-Software/DOOM https://github.com/id-Software/DOOM
- thefourthchime 7y agoI would read K&R, it’s a right of passage. Look at some of the larger open source projects for how to organize and manage a large c project. And practice pointers. Get really comfortable with how memory works.
- jerrysievert 7y agowhile not a definitive guide, https://matt.sh/howto-c https://matt.sh/howto-c is a good example of how to approach "modern" c. c99 is fully implemented in windows with msvc (2015), gcc, clang, and intel's compiler, so "right way" should not need to involve c89. most are c11 compliant as well.
- fergie 7y agoPretty obvious answer, but for those who are new to C, the C Programming Language by Brian Kernighan and Dennis Ritchie is a good place to start
- saagarjha 7y agoBest paired with a bunch of modern resources about how undefined behavior works.
- Areading314 7y agoI would recommend "Learn C the Hard Way" by Zed Shaw to get you started for something practical, because it goes over how C is written in the real world. Of course, situations will vary. The original book about C by K&R is an excellent book too.
- Paperweight 7y agoZed makes it clear in that book that he hates C and doesn't use it anymore due to its undefined behaviour.
- Areading314 7y agoSmart man!
- saagarjha 7y agoZed isn't actually very good at understanding undefined behavior and has demonstrated this loudly and repeatedly. I would steer clear of his book, personally.
- Jugurtha 7y ago> Zed makes it clear in that book that he hates C and doesn't use it anymore due to its undefined behaviour. Really? Which part in the book specifically if you can cite the passage.
- mrr54 7y agoLearn C the Hard Way is considered by the community to be, not exaggerating, one of the worst C books ever written.
- WalterBright 7y agoI'd just type in the examples from K+R, try them out, and modify them to do new things.
- elliotec 7y agoDo this but get the answer book too, because it's easy to get stuck in here.
- wiredfool 7y agoK+R is pretty ancient.
- WalterBright 7y agoSo is C :-)
- saagarjha 7y agoThat doesn't make it worthless; it's still probably the best book to learn C today if supplemented correctly.
- vocram 7y agoBecoming proficient in a language usually involves: - writing code with it long enough, - collaborate in a project based on it, - reading code other people wrote, - keep yourself up to date by following the language evolution, - go more in depth in language internals, compilers, etc... I wrote C for 10+ years (mostly bare metal FW), yet I am still amazed of how little I know about it. Recently for example I learnt of all the things the dynamic linker does in Linux, how symbols memory addresses are resolved at runtime using PLT, .... The good point about C is that it can be used for very different kind of projects, so the choices are a lot.
- stiray 7y agoThis was a pure satisfaction when I have first seen it :) https://en.wikipedia.org/wiki/Duff%27s_device https://en.wikipedia.org/wiki/Duff%27s_device
- 6c696e7578 7y agoThe C FAQ used to be a good place to start. Note, used to be: http://c-faq.com/ http://c-faq.com/ What did you want to do on Windows? I think this depends as much on the compiler as the code.
- camgunz 7y agoSecond this. Read it all more than once; the insights it will give you into C are so valuable. I'll also recommend C++ FQAs [1]. It's C++, yeah, but it's relevant to C in many places, and since a lot of systems programming now uses C++ as the lingua franca, it's a good, entertaining resource. 1: http://yosefk.com/c++fqa/ http://yosefk.com/c++fqa/
- makz 7y agoI'd say there's no proper way. Every project has its way of writing C. With the use of macros, sometimes it looks a bit like a DSL for every specific project. My advice: think about what kind of software you want to write and look for similar projects, libraries, or contribute with a new module, functionality, adapt something to your needs...
- pritovido 7y agoI would advice AVOID C macros at all cost. They are so weak and hard to debug and problematic. I write in several languages and read lots of C projects made by others and find the affirmation hard to believe: C is so simple that is very easy to read if the writer of code has a minimum of competency. You can say that of projects like C++, specially things like C++11 that are languages by committee so complex that you can affirm that every C++ programmer is different or find programmers that could not understand each coder's code. Not so with C. That happens to me with C++ and lisp code. It takes a while for me to understand what the author uses(or abuses) before being able to understand the code. That does not happen with C code.
- mrr54 7y agoThe Linux kernel uses lots of macros, many of them with lowercase names that are barely distinguishable from function names. Given the quality of that codebase, I think not using macros is a bit silly.
- iRobbery 7y agoBesides all that is mentioned already to read or do. I would suggest to try writing something you coded in python or go previously in C.
- pritovido 7y agoC is a very simple language. I have used just the official old book to create a compiler for it: https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628 https://www.amazon.com/Programming-Language-2nd-Brian-Kernig... The best thing you can do is finding some open source code that interest you, read it and write it. For example, I write my own controllers for CNCs, and there are lots of code for controlling stepper motors out there. I also learned OpenGL and sockets this way long time ago. On the other hand, C is a terrible language for any big project unless you automate it some way. I use mostly lisp in order to write C code automatically. C is too low level for writing any substantial code. Lisp has things like Macros(nothing to do with c macros) that can make you write code 10x, to 50x faster easily.
- 3fe9a03ccd14ca5 7y ago> The best thing you can do is finding some open source code that interest you, read it and write it. Has reading source code in a language that’s unfamiliar to you shown to be of any real benefit to learning? It seems you need at least a little bit of foundational experience with it before your brain can even parse what you’re seeing in a beneficial way.
- dandigangi 7y agoI'd tend to agree here also. I didn't start reading source code until a couple years in because I couldn't really put it to use. It becomes 10x more valuable when I was deep into my career learning from the big shots. It _can_ help no doubt but not sure that's the best way to start. Especially with a language like C. It's not so straight forward without some training or CS education.
- clarry 7y ago> It becomes 10x more valuable when I was deep into my career learning from the big shots. Yeah well OP said they've 15+ years of experience so.. > Especially with a language like C. It's not so straight forward without some training or CS education. I agree with pritovido, when they say C is a very simple language. Sure, it has grown its quirks and gotchas along with some cruft (the kind of things you wouldn't learn about in a CS curriculum anyway), but at its core it really is very simple.
- ryan-allen 7y agoI'd check out Zed Shaw's book [0]. It's opinionated, but I think that's a good thing for something like C. It's broken up into exercises that you start working through straight away, and you start early with valgrind. [0] https://learncodethehardway.org/c/ https://learncodethehardway.org/c/
- saagarjha 7y agoThe author of that book doesn't really like C, and it shows. And valgrind is usually not the first tool you should be using to debug memory issues–try Address Sanitizer instead.
- tmotwu 7y agoLike anything else, set yourself a goal for a project. What kinds? C today is typically used for developing embedded systems, kernel internals, or device drivers. Depending on how deep you want to go. The most in depth way to understand C is to learn assembly on an ISA first.
- vbtemp 7y agoFirst step is making sure you're using the flags `-Wall -Werror -pedantic` and then one of `-std=c89` or `-std=c99` (Or equivalent in whatever Windows C compiler)
- giomasce 7y agoWhy would you suggest older versions?
- stephc_int13 7y agoIn my opinion, one of the main reasons C looks old and not practical to beginners is the standard libs API. But it is perfectly possible to use C as a language with a more modern and easier to read API, but you'll probably have to build your own.
- jakobdabo 7y agoIn addition to the other recommendations, make sure you fully understand the memory model of your target architecture, the stack, the heap, the linkage. Also, understand the undefined behavior, the compiler optimizations and how it can affect your code if you forget about the UB or if you ignore the compiler warnings, and read about the `volatile` keyword. And a personal tip, please tell the compiler not to use strict aliasing (I think it's stupid) - you will get rid of some UB without much sacrifice.
- krychu 7y agoJust to be clear, heap and stack are not part of C.
- Canada 7y agoThen why does it make a difference whether you dereference a pointer to the stack or the heap at any point in your program? The hardware representation of an int isn't part of C either but it most certainly had an effect on how your program will run.
- clarry 7y ago> Then why does it make a difference whether you dereference a pointer to the stack or the heap at any point in your program? Ok, I'll bite. What difference does it make?
- smcameron 7y agoBecause stack pointers are short lived, while heap pointers can be longer lived. Say you have a queue of pointers that some thread is chewing on, you can't stick a pointer to a stack variable into that queue and then exit the scope of that stack variable, but you could put a longer lived heap pointer into that queue and exit the scope of the pointer, essentially passing ownership of the pointer to whatever's chewing on the other end of the queue.
- 7y ago
- dandigangi 7y agoI learned a few basic levels of C using my subscription to pluralsight.com. But... I quickly switched to Rust as I see it being the C of the future as it continues to develop. That's just me though. (I have similar opinions towards things like Kotlin or Go.) The books I am reading in the comments below are great resources.
- haolez 7y agoI would focus on sources that use C11 or C18, since there are some niceties in the newer standards. As a reference, I like QEMU's source code[1]. It's huge, but the style and practices found in any file will help you get a grip on good C. [1] https://github.com/qemu/qemu https://github.com/qemu/qemu
- jfkebwjsbx 7y agoYou can compile with clang on Windows, so you can use later standards.
- chucksmash 7y agoI liked "C Programming: A Modern Approach"[1]. It has been several years but as I recall it was well suited for self study and was pretty explicit in calling out places it was talking about C99 as opposed to C89. [1]: https://www.amazon.com/C-Programming-Modern-Approach-2nd/dp/0393979504 https://www.amazon.com/C-Programming-Modern-Approach-2nd/dp/...
- chucksmash 7y agoYou might also take a look at this Minecraft clone in C[1]. Uses sqlite to persist state so you can see how you might interact with a database as well. Quite modern and readable in that most functions outside main.c are <20 lines long. It's also cross platform and should work on Windows, Mac and Linux. [1]: https://github.com/fogleman/Craft https://github.com/fogleman/Craft
- krychu 7y agoThe proper way to learn C is to get a good book, read it, and do exercises along the way. Here’s an excellent book: C Programming: A Modern Approach, by King. Avoid online tutorials, and know that there are many poor books on C, including the recommended here “Learn C the Hard Way”. It has factual problems; see under “Stuff that should be avoided” here: http://iso-9899.info/wiki/Main_Page http://iso-9899.info/wiki/Main_Page Note also, that unlike some other languages, C is not a language that you should learn by “trying things out”, due to the nature of “undefined behavior”. Another recommendation would be to ask for CR on IRC. Good luck!
- ianai 7y agoI’m always skeptical of telling people to not just try something out in programming. Yes, don’t just try to code up the next unix without knowing any c. But definitely getting your hands dirty isn’t going to instill any super bad mental/coding practices.
- geofft 7y agoC is a particularly weird language: it's entirely possible for things to work but - secretly introduce security vulnerabilities - stop working on a different compiler or after a compiler upgrade A generation of C programmers learned by trying things out, and they left us with superstitious beliefs about volatile (and also with imprisoned Uyghurs in China). We have the evidence and learning C by trial and error doesn't work. If you're going to write C (and there are definitely places where it's the right thing to use), learn it with more caution than you'd learn other languages.
- StrangeDoctor 7y agoOk I’ll bite, what on earth is the connection between Uyghurs and C?
- saagarjha 7y agoPresumably the fact that iOS had vulnerabilities that allowed for watering-hole style zero-day attacks on Uyghurs in China.
- PureParadigm 7y agoC is great for learning about how computers work at a low level. In my college, we started by writing a simple compiler. This should force you to understand pointers and memory which, as others have mentioned, are fundamental. You'll have to both know how the assembly works and to write correct C code. So writing a simple compiler will force you to understand it two different ways at once. My opinion is you'll learn more by diving in and doing things, especially with your existing programming background. But, for your own sanity and everyone else's, do not start new projects in C! (Aside from purely academic ones for you to learn.) The point of a programming language is to help humans write safe and correct code. In this sense, C has completely failed. The syntax itself is just begging you to make a subtle mistake. And due to lack of memory safety, even the most well tested and scrutinized projects in C/C++ (such as Chromium) suffer from buffer overflows or memory leaks, potential security vulnerabilities that are automatically prevented by design in other languages. If you need to do something low level with any sort of confidence, use a memory-safe language like Rust, which can even do interop with existing C libraries and code. (Edit: typo)
- bronipstid 7y agoIt depends on what you're doing. Low level stuff pretty much has to be C. But for applications I agree there are much better alternatives these days.
- PureParadigm 7y agoYeah, there may be some situations where C is necessary as a wrapper for assembly if you're _extremely_ memory constrained or something like that. But I wouldn't have any confidence in it working as intended unless it's dead simple.
- saagarjha 7y ago> The syntax itself is just begging you to make a subtle mistake. C's syntax is fine (if a bit ugly around declarations), it's really the memory safety that gets you.
- tedunangst 7y agoRadical suggestion: read the C standard.
- kevindong 7y agoAsking someone to read a multi-hundred page standards document just to learn the language is wholly unreasonable.
- clarry 7y agoWell, OP asked for source of truth. Nothing comes as close as the standard itself. Honestly, I think any programmer writing C today should have it around for reference. And yeah you kinda need to read it too, or you won't be able to refer much. That said, no need to read it cover to cover. There's stuff one can earmark as being there but ignore until it's actually needed (for example: the grammar and all the library functions). And speaking of tedu, I would recommend to the OP that they get in the habit of checking out the OpenBSD man pages for libc functions.
- sramsay 7y agoI actually have very few $200 PDFs lying around. Do you really go purchase the standard documents from ISO? Or does your employer? I'd love to have the actual standard "around for reference," but 700-page technical documents from ISO are not cheap.
- clarry 7y agoThe next best thing is the latest draft standards, which are available online for free (and I always have them on my laptop, PC, and personal server). Differences between them and final official standard are not important. Search for N1256, N1570. Or grab them here. http://www.open-std.org/jtc1/sc22/wg14/www/standards http://www.open-std.org/jtc1/sc22/wg14/www/standards (There are more readable html versions floating about)
- kevindong 7y ago
- deleted 7y ago[deleted]
- sramsay 7y agoIt sounds like you're not asking, "How do I learn the language?" but "How do I know I'm doing it right?" I think Gustedt's book is superb if you're just trying to learn the language, and it does a good job of presenting the most up-to-date standard. I admire the K&R as much as anyone else, but it's not exactly an up-to-date language resource at this point, and it doesn't really provide any guidance on the design and structure of systems in C (that's not it's purpose). You might have a look at Hanson's C Interfaces and Implementations: Techniques for Creating Reusable Software. That's focused on large projects and APIs, but it will give you a good sense of the "cognitive style" of C. 21st Century C is very opinionated, and it spends a great deal of time talking about tooling, but overall, it's a pretty good orientation to the C ecosystem and more modern idioms and libraries. I might also put in a plug for Reese's Understanding and Using C Pointers. That sounds a bit narrow, but it's really a book about how you handle -- and think about -- memory in C, and it can be very eye-opening (even for people with a lot of experience with the language). C forces you to think about things that you seldom have to consider with Javascript, Python, or Go. And yes: it's an "unsafe" language that can set your hair on fire. But there are advantages to it as well. It's screaming-fast, the library ecosystem is absolutely gigantic, there are decades of others' wisdom and experience upon which to draw, it shows no signs of going away any time soon, and you'll have very little trouble keeping up with changes in the language. It's also a language that you can actually hold in your head at one time, because there's very little sugar going on. It's certainly possible to write extremely obfuscated code, but in practice, I find that I'm only rarely baffled reading someone else's C code. If I am, it's usually because I don't understand the problem domain, not the language.
- johnisgood 7y agoI also recommend https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Coding+Standard https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Cod....
- emily-c 7y agoI second every book recommendation here. Another great one is The Standard C Library.
- bsder 7y ago
- deleted 7y ago[deleted]
- vineel567 7y agoI am in the same boat as you are...bare with me by no means I am an expert. In fact, I read couple of chapters in Modern C yesterday :). Here are some of the things I am doing to improve my C skills to match with some of the admired/professional developers. Decide which platform to use ~~~~~~~~~~~~~~~~~~ Unfortunately, to become proficient in it we need to write code and focus on a platform. I have been fighting between whether to develop on Windows vs Linux. I am very experienced in Windows environment(using debuggers/cl/linkers/Windbg etc) but when it comes to writing good quality C code(not C++) and for learning how to write good maintainable moderately large source code, my research showed that Windows compilers/C standard APIs are not great, in fact they hinder your productivity. I have wasted countless number of hours to just figure out how to properly create a simple C project with a decent build system. Unfortunately, I could not find one. The closest I could find is CMake as MSBuild is a nightmare to work with. I even tried NMAKE but failed. When it comes to documentation of finding basic C Api usage, MSDN(https://docs.microsoft.com/en-us/cpp/c-runtime-library/run-time-routines-by-category https://docs.microsoft.com/en-us/cpp/c-runtime-library/run-t...) does a decent job. But in the name of security you will find zillion variations(_s, _l) of an API and by default msvc compiler will not let you use some of the API in their simple forms. Instead, you have to define _CRT_SECURE_NO_WARNINGS etc. I think for someone just getting started to develop/learn to write a decent code base in C these restrictions really hinder the productivity. So finally, I have decided to instead focus my learning on Linux platform(currently through WSL - Windows subsystem for Linux) with its POSIX apis. You know what, `man 3 printf` or `man 3 strlen` is soooooo much better than googling msdn Mastering C ~~~~~~~ I think, the simple and straight answer here is reading good code and writing "good" code and also reading good C content(be it books or articles). I think these are the three ingredients necessary to get started. Of all the open source projects that I have investigated, I found Linux Kernel and related projects seems to have very good taste in terms of code quality. Currently, I am just focused how they use the language rather than what they actually do in the project. Things like, how they structure the project, how they name things, how they use types, how they create structures, how they pass structures to function, how they use light weight object based constructs, how they handle errors in function(for example forward only goto exits), how they use signed/unsigned variables etc(more of my learnings to the end), how they use their own data structures. I think its good to initially focus/target on ANSI C API with C99 instead of heavily relying on the OS specific API on which ever platform you choose. For example, such projects could be writing binary file parsers for example projects like .ISO file format etc. Good C projects/articles ~~~~~~~~~~~~~~~ 1. Winlib.net - https://github.com/jcpowermac/wimlib https://github.com/jcpowermac/wimlib is a great source of information 2. e2fsprogs - https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/ https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/ 3. MUSL - https://git.musl-libc.org/cgit/musl/tree/ https://git.musl-libc.org/cgit/musl/tree/ 4. General C Coding Style - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/coding-style.rst https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin... 4. https://nullprogram.com/tags/c/ https://nullprogram.com/tags/c/ - great source of C knowledge 5. CCAN - https://github.com/rustyrussell/ccan/tree/master/ccan https://github.com/rustyrussell/ccan/tree/master/ccan - great source of C tidbits from none other than Rusty Russell - I haven't read all of them 6. POSIX 2018 standard - https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/ https://pubs.opengroup.org/onlinepubs/9699919799.2018edition... continued in the comment....
- gjkood 7y agoTo start with, "The C Programming Langauge", Kernighan & Richie (K & R) [1]. Find the latest edition that you can buy. I think the primary topic to master in C is pointers. This is where most falter. It takes a few years to "master" (if we ever do). Here I would recommend "Understanding and Using C Pointers", Richard Reese. [2] If you are interested in networking, any of the classic "TCP/IP Illustrated Vols I/II/III", W. Richard Stevens, [3] contain a ton of C code to implement components of TCP/IP. If you are interested in Graphics, then "Graphics Gems", Andrew Glassner [4] is a good source. "An Introduction to GCC", Brian Gough, [5] to understand the tooling and its various bells and whistles. My learning swimming by jumping into the deep end of the pool experience was realized by learning Windows Programming using the Charles Petzold book and navigating through Microsoft Foundation Classes in the late 80s/early 90s. The state of the art in tooling wasn't that great in those days and I spent months with the book to get things going. This was done after I had built a foundation with K&R and a decent amount of Unix network programming. I see a lot of the other posts recommend more modern books. But you still need to build your foundation on C and Pointers in particular. Good luck on your journey. [1] https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628/ref=sr_1_1?crid=2FEGL0ITD7BO&keywords=the+c+programming+language&qid=1583705302&sprefix=The+C+Progra%2Caps%2C212&sr=8-1 https://www.amazon.com/Programming-Language-2nd-Brian-Kernig... [2] https://www.amazon.com/Understanding-Using-Pointers-Techniques-Management/dp/1449344186/ref=sr_1_2?crid=32I1T4I421WPZ&keywords=understanding+and+using+c+pointers&qid=1583705390&sprefix=Understanding+and+Using+C+P%2Caps%2C221&sr=8-2 https://www.amazon.com/Understanding-Using-Pointers-Techniqu... [3] https://www.amazon.com/TCP-Illustrated-Protocols-Addison-Wesley-Professional/dp/0321336313/ref=sr_1_1?crid=V0LZ9TYHEOFS&keywords=tcp%2Fip+illustrated&qid=1583705448&sprefix=TCP%2Fip+%2Caps%2C222&sr=8-1 https://www.amazon.com/TCP-Illustrated-Protocols-Addison-Wes... [4] https://www.amazon.com/Graphics-Gems-Andrew-S-Glassner/dp/0122861663/ref=sr_1_1?crid=1WEA9UYLALBRE&keywords=graphics+gems&qid=1583705599&sprefix=Graphics+Ge%2Caps%2C212&sr=8-1 https://www.amazon.com/Graphics-Gems-Andrew-S-Glassner/dp/01... [5] https://www.amazon.com/Introduction-GCC-GNU-Compilers/dp/0954161793/ref=sr_1_1?crid=1L8K7ERCL07RZ&keywords=an+introduction+to+gcc&qid=1583705516&sprefix=introduction+to+GCC%2Caps%2C218&sr=8-1 https://www.amazon.com/Introduction-GCC-GNU-Compilers/dp/095...
- ajb 7y agoRead John Regehr's blog, eg https://blog.regehr.org/archives/213 https://blog.regehr.org/archives/213 Read "Who Says C is simple?": http://cil-project.github.io/cil/doc/html/cil/ http://cil-project.github.io/cil/doc/html/cil/ Take up a different language :-)
- fhars 7y agoEssential reading: https://blog.regehr.org/archives/213 https://blog.regehr.org/archives/213 http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html?m=1 http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
- jstimpfle 7y agoomg no. Stop obsessing about this dragon. I'm not sure I've ever met it in my life (you know, other than segfaults from NULL dereferences which are UB too).
- saagarjha 7y agoHow much C have you written, and how much has gone through a high-performance optimizing compiler?
- jstimpfle 7y agoI don't know. Quite a bit - maybe written 300K lines and deleted > 200K lines. Most of it was compiled by gcc -O2 and/or MSVC. I've never relied on vectorization or used a lot of intrinsics, though.
- jennyyang 7y agoGet code reviews from someone that actually knows C. Mentorship and harsh code reviews are the best way to learn.
- lmilcin 7y agoGiven the fact you already know some higher level languages I think the best way to learn C is to go low level. C is fantastic language because it is within your reach to go and understand all small details of how various features are actually implemented. I find it very helpful to be able to understand how a piece of code actually functions on a low level. Another tip: you are used to having high level features on your disposal. Don't try to duplicate those features. Figure out how actual C projects deal with program structure and flow issues that you are used to solving with high level constructs.
- unnouinceput 7y agoThis^! +1 Also do it on a Raspberry Pi, it will allow to touch that low level better. Only flashing an LED through GPIO pins and is enough to grasp the basics.
- __s 7y agoCPython is a particularly nice codebase to dig into. Plus, there's a big todo list: https://bugs.python.org https://bugs.python.org
- jussij 7y ago> Note, I'd like my C code to work on Windows, which possibly restricts the "right way" to features provided by C89 That might be the case if you plan to use the Microsoft C compiler as they have publicly said the don't have plans to update their C compiler. However that is not your only option, since clang and several GCC ports will also work on Windows.
- giancarlostoro 7y agoAre you not able to use their C++ compiler to get modern features? My understanding is that C++ is a superset and that a C++ compiler is also usually a C compiler. Is this view incorrect for modern implementations?
- jstimpfle 7y agoIt's not strictly a superset, to the point that there are good reasons to stay with a C compiler other than to simply stay sane. I make a lot of use of designated initializers for laying out static const arrays. And I actually don't like the way that structs in C++ can be referred to both with and without the struct tag. I also don't like how void-pointers are not compatible with other pointers without an explicit cast. Or that plain integers cannot be assigned to enum types. Some of this is just my personal preference (or Stockholm Syndrome), but the fact is that most C code will fail to compile as C++ without some changes. MSVC is probably pretty close to C99 these days. Designated initializers are C99, for example.
- Leherenn 7y agoYou can assign integers to enum in C++, just like in C, but not to enum class. Use the latter when you need type safety, the former when you need to easily convert integer <-> enum, which apart from (de)serialisation is rare in my experience. And even in those cases, I personally prefer the explicit casts. As far as I know, MSVC just implements the C subset of C++.
- jstimpfle 7y ago
- deleted 7y ago[deleted]
- deleted 7y ago[deleted]
- quelsolaar 7y agoOnce you know the basics watch this: https://www.youtube.com/watch?v=443UNeGrFoM https://www.youtube.com/watch?v=443UNeGrFoM ;-)
- johnisgood 7y agoIn Modern C (book mentioned by OP), there is takeaway 2.11.1.14 which says "Don't use NULL" because: The definition in the C standard of a possible expansion of the macro NULL is quite loose; it just has to be a null pointer constant. Therefore, a C compiler could choose any of the following for it: 0U, 0, '\0', 0UL, 0L, 0ULL, 0LL, or (void * )0. It is important that the type behind NULL is not prescribed by the C standard. Often, people use it to emphasize that they are talking about a pointer constant, which it simply isn’t on many platforms. Using NULL in a context that we have not mastered completely is even dangerous. This will in particular appear in the context of functions with a variable number of arguments. NULL hides more than it clarifies. Either use 0 or, if you really want to emphasize that the value is a pointer, use the magic token sequence (void * )0 directly. https://www.gnu.org/software/libc/manual/html_node/Null-Pointer-Constant.html https://www.gnu.org/software/libc/manual/html_node/Null-Poin... says: The preferred way to write a null pointer constant is with NULL. You can also use 0 or (void * )0 as a null pointer constant, but using NULL is cleaner because it makes the purpose of the constant more evident. If you use the null pointer constant as a function argument, then for complete portability you should make sure that the function has a prototype declaration. Otherwise, if the target machine has two different pointer representations, the compiler won’t know which representation to use for that argument. You can avoid the problem by explicitly casting the constant to the proper pointer type, but we recommend instead adding a prototype for the function you are calling. https://man.openbsd.org/style https://man.openbsd.org/style says: NULL is the preferred null pointer constant. Use NULL instead of (type * )0 or (type * )NULL in all cases except for arguments to variadic functions where the compiler does not know the type. --- Readers: what is your take on it and why?
- saagarjha 7y agoUse NULL, this is what it's for. 0 will convert the the NULL pointer representation, but the NULL pointer representation is not required to be bitwise identical to 0.
- ajross 7y ago> Readers: what is your take on it and why? All the bad stuff that people on both sides of this argument predict is going to happen somewhere in some code base, precisely because people on both sides can't agree and think the world would be better if everyone agreed on those people's personal aesthetic ideals. So... don't sweat it. Conform to whatever code base you're working on has decided, and if it's inconsistent work to make it so. And above all, no matter what else: Don't start dumb fights over this nonsense. Yeesh.
- juped 7y agoThis is actually pretty hard. I recommend reading C codebases, but it can be hard to know which ones are good. Code to C99 for now; keep an eye on C11 etc. Have a personal library of C implementations of things. Don't worry about being on Windows, although if you're doing Windows development C#/.NET is the lowest friction path. I'm writing a book on C. I don't think it will ever be finished or see publication. I recommend writing a book yourself - it's a great way to learn, and maybe you're a better writer than me and will publish it.
- keithnz 7y agoThere is no clear source of truth for C. Depending on what you want to do there is quite different approaches. C for embedded systems tends to look quite different from C for systems programming. For instance MISRA is a C coding standard for embedded devices in Motor Vehicles (but many of its ideas are ideas from writing robust embedded systems), it says don't use things like dynamic memory. You'd never use that if you are writing software for linux/windows. So learning C "properly" would be about learning the different approaches people use in C to write robust code and what tradeoffs they are making. Understanding the C standard and the variations. Understanding bare metal programming. Understanding the effect of different underlying processors and hardware architectures. Understanding systems programming and how to consume APIs and how to create reusable binary modules. Understanding the compiler/build system the intermediate files / code generation / memory layout. Read a variety of books ( including K&R ) and study code ( Luas implementation is some very nicely written C )
- begriffs 7y agoIt's hard to beat this list of quality books: http://iso-9899.info/wiki/Books#Learning_C http://iso-9899.info/wiki/Books#Learning_C Read some and do the exercises. You'll learn to write portable code to a standard rather than stuff that "accidentally works." There's a lot of crap C code in the world, full of GNUisms, overzealous macros, header-only nonsense abusing translation units, and copypasta. Don't pick up bad habits from that stuff.
- guerrilla 7y agoIt's not easy. The obvious answer is read and write lots of code. Experiment. Make sure you actually know how a computer works. Learning some assembly even if you don't ever use it can help with that (free ebook "Programming from the Ground up" can be done in a weekend) Read existing code bases, different styles, like linux or some GNOME stuff.
- pyuser583 7y agoIf you’re an experienced programmer, with some understanding of C, I recommend: “Expert C Programming: Deep Secrets” by Peter van der Linden. It’s one of the best books in the world. About anything. Ever.
- jjgreen 7y agoI was going to post the same, now I don't have to, fabulous book.
- carapace 7y agoLearn (a little bit of) assembly first. It will make more sense IMO if you came at it from below rather than above, so to speak.
- bane 7y agoThe most important difference between a higher level language and C is that you really have to understand a bit about the underlying hardware architecture to do it "right". C is a fairly thin veneer over assembly and it helps to have that mental model in mind when working in it. It's a very small language with almost no batteries included, built very much around the manipulation of pointers and memory more than just about anything else. To do C the "right" way means approaching problems from that perspective and building mountains out of toothpicks while thinking about how the billions of toothpicks need to interact with one another so they don't crash/catch fire/etc.
- ndesaulniers 7y agoI work on Clang and the Linux kernel. JavaScript was the first language I feel I've mastered, before C. Of the many C books I have and have read, I only recommend 2: Head First C by Griffiths and Griffiths Expert C Programming: Deep C Secrets by van der Linden The first is an excellent introduction, especially if you treat it as a workbook. The second is a great intermediate book. Really advanced stuff comes from seeing things in the wild.
- ndesaulniers 7y agoAlso, Jens' book is great, and I've learned from reading it, but it is way too long for a beginner.
- master_yoda_1 7y agoThis is a fun book to start with "Expert C Programming Pete van Linden" https://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298 https://www.amazon.com/Expert-Programming-Peter-van-Linden/d...
- m0rphling 7y agoIf you're into visual/interactive learning, please give Harvard's CS50 a try. https://www.youtube.com/channel/UCcabW7890RKJzL968QWEykA https://www.youtube.com/channel/UCcabW7890RKJzL968QWEykA https://cs50.harvard.edu https://cs50.harvard.edu
- bryanwb 7y agoAn important question to ask yourself is why do you want to learn C? If you want to be able to read large C codebases makes sense. But if you want to write embedded software or systems software, rust or c++11 (ugh) are arguably a better place to start. I say this as someone who has learned C but moved on to c++ without regrets. Though I have serious rust envy :)
- cryptonector 7y agoWith C++, going modern-first is a great approach. But C hasn't really been modernized that much, and because Microsoft has been so slow to fully support even just C99, let alone C11 or any GCC/clang extensions, often one has to to stick to a subset of C99 anyways -- exactly as you surmised. The problem with C is that it's extremely dangerous. Besides learning how to program in C, you'll really want to know how to use memory debuggers such as valgrind and Dr. Memory (https://www.drmemory.org/ https://www.drmemory.org/), as well as AFL for fuzzing, and various GCC and clang sanitizers. You'll really want to let functional programming language experience inform your approach to C API design and implementation.
- pjmlp 7y agoMicrosoft hasn't been slow, they have been quite clear, C is legacy on Windows, given its security implications, all new code should be C++ and the compiler is called Visual C++ after all. C support is done to the extent of ISO C++ requirements. For those that still want to use plain old C on Windows, they have contributed to clang, and it is now available as part of Visual Studio installer.
- makach 7y agoFinding "the right way" is closer to religion than it is to problem solving and science. You will always be vulnerable to criticism and other people's opinions, and you need to open up and acknowledge this fact and work with that. There are best practices and principles you can adhere to. Stand up for your design decisions, and refactor when you have to.
- _benj 7y agoI’m currently learning C myself and something that I realized is that often the hard part to learn is not C the language but the domain in which is being used. For example, I’m trying to learn Linux drivers or embedded programming and I thought that I’d find in a C book information about registers and such, but registers don’t really belong to the C domain but to the hardware domain. Thus, maybe find a way to clarify what you want to use C for and then learn those domain problems and how C solves them.
- Nursie 7y agoThere are other compilers for windows than MSVC++, so you can move beyond C89 if you wish. stdint.h is useful and should be required reading. I still come across too many C projects that reimplement it poorly. Learn to use valgrind, and maybe ddd too.
- grafelic 7y agoAn interesting way IME to learn C, is to code for an old platform like the Amiga. All the same best practices apply, but the underlying OS is more simple and the constraints, like missing floating point, forces you investigate many aspects of C. You can use Bebbo's m68k cross compiler to compile for the platform: https://github.com/bebbo/amiga-gcc https://github.com/bebbo/amiga-gcc No single source of truth for C best practices exist, but I can recommend using static analyzers like: https://splint.org/ https://splint.org/ and http://cppcheck.sourceforge.net/ http://cppcheck.sourceforge.net/ to steer you in the right direction. Also, compile your code with the following gcc options: -pedantic -std=<c99 or c89> -ggdb3 -O0 -Wall -Wextra -Wformat=2 -Wmissing-include-dirs -Winit-self -Wswitch-default -Wswitch-enum -Wunused-parameter -Wfloat-equal -Wundef -Wshadow -Wlarger-than-1000 -Wunsafe-loop-optimizations -Wbad-function-cast -Wcast-qual -Wcast-align -Wconversion -Wlogical-op -Waggregate-return -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wpacked -Wpadded -Wredundant-decls -Wnested-externs -Wunreachable-code -Winline -Winvalid-pch -Wvolatile-register-var -Wstrict-aliasing=2 -Wstrict-overflow=2 -Wtraditional-conversion -Wwrite-strings Not that they all necessarily always makes sense, but they will reveal weak points in your code.
- flohofwoe 7y agoThe Visual Studio C compiler (not the C++ compiler) supports "almost all" of C99, I would definitely recommend skipping C89, and use at least the new initialization features from C99 because they can reduce bugs caused by uninitialized data. Also, C++ compilers support a subset C99 that's somewhere around "C95" and is already a much friendlier version compared to C89. TBH, I think the best way to learn C is to tinker a bit with assembly first (it doesn't have to be a modern assembly dialect, just write a few 6502 or Z80 assembly programs in a home computer emulator). Coming from "below" instead of "above" C's abstraction level helps understanding the design rationale behind C, and the trade-offs between flexibility and unsafe memory handling.
- Foobar8568 7y agoI am currently relearning C, I tried different books over the years (to not say decades), never did more than a toy project. The book I picked up this time was extreme c (from Amazon reviews, failry new book), by Kamran Amini, and so far (few chapters in) it's fairly enjoyable as it takes C, compilation process etc from the "basics", fairly hands-on and not too much theorical and relatively fast paced. I feel that the book is more about how to make a program C and not teaching literally the language itself. So really what I needed.
- springogeek 7y agoProgramming in C requires you to take proper responsibility for what you write, but also allows for great power in return. I've been working on a reasonably large (and cross platform) project in C (https://domeengine.com https://domeengine.com) for a couple years now, and I find that C generally requires a certain kind of discipline. When you interact with an API, you need to read the docs, figure out their specific preconditions, and requirements on handling frees, establishing what you own and what you don't. It also helps to make sure that if you allocate something, you clean up after in a clear and well defined way. You should also get very familiar with debuggers (LLDB/GDB) and other dev tools, to help when you have made a mistake. In the modern era, you have a couple of options for getting it to run on Windows. C89 using Visual Studio, The MSYS2/MinGW2 gcc toolchain, or a gcc toolchain using the WSL. I use the MSYS2 tools for DOME because it requires the fewest platform-specific modifications to my code, but this varies by usecase.
- drran 7y agoI use C since 1992, but I never confident in my C code, unless it heavy with macros to check error codes and return early, register memory allocations and free memory at return, and so on. Rust improved my confidence in C code a lot, but it looks more like Rust code now.
- justforfunhere 7y agoAll the advice already here is very good and implementable. Here are my two cents. I have been programming in C professionally for the past 12 years, and I think the way to go would be to go implement a well known tool in C and then compare your code with the open source code of that tool. e.g. Git. You will learn a lot from how the feature that you chose to implement in a certain way was implemented in a completely different way for various reasons.
- LessDmesg 7y agoScrew C, really. Let this crappy old language die off quietly. Learn Zig (the best replacement for C) or at least Rust.
- enesunal 7y agoEssential parts of C language are actually really a small set. What I'd suggest is, learn syntax and try to understand linux kernel (which is one of the very well crafted software piece we have written in C). If you don't want to go that much of a deep dive, you can check sqlite source code as well. Writing code starts with reading it. Do yourself a favour and spend more time on reading code than reading books.
- LocalMan 7y agoI've written many tens of thousands of lines of C, but retired 15 years ago. The two best books I know are: 1. C: A Reference Manual, by Harbison and Steele. https://www.amazon.com/Reference-Manual-Samuel-P-Harbison/dp/013089592X/ref=dp_ob_title_bk https://www.amazon.com/Reference-Manual-Samuel-P-Harbison/dp... 2. The C Puzzle Book, by Alan Fueur. https://www.amazon.com/Puzzle-Book-Alan-R-Feuer/dp/0201604612 https://www.amazon.com/Puzzle-Book-Alan-R-Feuer/dp/020160461... Harbison and Steele has much better explanations than K&R. The Fueur book taught me a lot about C declarations. Declarations are that part of C language that is them most unnecessarily difficult. You asked about a slightly different question, best practices. But in the real world you'll run into a lot of code that practices below that level.
- msaqib8181 7y agoI think you can use any version of Visual studio to write C programs. I recently did a video tutorial using Visual Studio: https://www.youtube.com/watch?v=JaDzgmZvY00 https://www.youtube.com/watch?v=JaDzgmZvY00 on the "C++ Modulus Operator" https://www.mycplus.com/tutorials/cplusplus-programming-tutorials/the-c-modulus-operator/ https://www.mycplus.com/tutorials/cplusplus-programming-tuto...