14 ms·
To become a good C programmer (2011)
- yesenadam 7y agoThis is a great list of books - at least, I found the same ones were the most excellent. Also I really learnt a lot from 21st Century C (The author here said they wanted to stick to C89, which is fair enough.) >To read great C code will help tremendously. But then he just gives examples of games I don't know and am not really interested in. Anyone know some non-game C that is, I suppose, well-known and wonderfully-written? Also, am learning about writing APIs, any good books or talks about that people could recommend, or examples of particularly good ones in C? (I'm particularly interested in maths/graphics-type stuff.) Thanks!
- jraph 7y agoI find the source code of the Netsurf browser really beautiful: - https://netsurf-browser.org/ https://netsurf-browser.org/ - https://source.netsurf-browser.org/netsurf.git/tree/ https://source.netsurf-browser.org/netsurf.git/tree/ Including the sub projects, for instance: - https://source.netsurf-browser.org/libcss.git/tree/ https://source.netsurf-browser.org/libcss.git/tree/ - https://source.netsurf-browser.org/libdom.git/tree/ https://source.netsurf-browser.org/libdom.git/tree/ It feels immediately obvious and understandable, which is quite impressive for a browser. Everything is well documented, well separated, the code is clean and seems simple, functions are small, etc. I am really impressed. I'd want to work on such code. I have never worked on it though, and I am not connected in any way to this project.
- needs 7y agoVery well written code indeed. Thanks for the links. They could make error management less bug prone by using goto, but it's definitely high quality C code nonetheless.
- rhoyerboat 7y agorecently I started working on a module for nginx and have developed a full-blown crush on the module loader and its relationship with core functionality. haven't seen anything else quite like it, in C, that is. major newb talkin' also plan9, its nice to read some kernel code that hasn't been tortured by practical requirements for decades.
- fabiensanglard 7y agoI recommend git source code which was pretty neat last time i checked.
- eindiran 7y agoThe sqlite codebase is well-known for being a large, well-written C codebase: https://github.com/sqlite/sqlite https://github.com/sqlite/sqlite The tests in particular are very impressive. Some other notable C codebases: Redis, LuaJIT, FreeBSD, Memcached --> https://github.com/antirez/redis https://github.com/antirez/redis https://github.com/LuaDist/luajit https://github.com/LuaDist/luajit https://github.com/freebsd/freebsd https://github.com/freebsd/freebsd https://github.com/memcached/memcached https://github.com/memcached/memcached
- jacquesm 7y agoVarnish and the Linux kernel should be in that list as well I think.
- eindiran 7y agoNice! Here are the links: Varnish --> https://github.com/varnishcache/varnish-cache https://github.com/varnishcache/varnish-cache Linux Kernel --> https://github.com/torvalds/linux https://github.com/torvalds/linux
- fanf2 7y agoPostgreSQL’s source code is also really good. https://git.postgresql.org/gitweb/?p=postgresql.git;a=tree https://git.postgresql.org/gitweb/?p=postgresql.git;a=tree
- atq2119 7y agoThe core Linux kernel is well-known and mostly well-written C.
- ndesaulniers 7y agoI'd say "advanced" C, not necessarily "well-written" C. There's certainly a lot of C in it, and I'd bet it's the largest open source C codebase.
- cesarb 7y agoThey go beyond C, it's actually C + GCC extensions. The only reason clang can compile it (in some configurations) is that they painstakingly implemented each of the GCC extensions the kernel uses (and when they were almost done, the kernel started requiring a few more).
- stebann 7y agoThis is a good list because it isn't a gigantic compendium about C.
- fredsanford 7y agoI consider [0] to be well written and fairly low fat. 0 https://github.com/Genymobile/scrcpy https://github.com/Genymobile/scrcpy
- sandov 7y agoI think you pasted the wrong URL.
- aphextron 7y agoWhy does everyone always suggest K&R? I really don't see the big deal. It's short, contains only trivial toy examples with no real world application, and touches almost nothing on actual project architecture or best practices. I bought it expecting to learn to write programs in C but it's really just a reference manual on syntax.
- Timpy 7y ago> It is all you need to know about C…for the first few weeks. It seems the author was aware of this. Isn't syntax a good place to start for a new language?
- fabiensanglard 7y agoIn short: It is a great starter. The book is so tiny it won't discourage people and get them going in no time.
- aikah 7y ago> Why does everyone always suggest K&R? Because it's the best no bullshit book to learn C, period. Especially coming from garbage collected languages. It's not going to teach you valgrind or GDB, or even compile and link C programs but it will certainly teach you how to write C programs. > only trivial toy examples with no real world application Re-implementing POSIX commands is writing real world applications. > and touches almost nothing on actual project architecture or best practices. On what platform? Linux? Windows? Mac? tool chains are so different on all these platforms that it wouldn't make sense to spend time on that. That books is about C, not learning autotools and other horrors.
- globular-toast 7y ago> trivial toy examples with no real world application It teaches you how to write malloc. Plenty of the examples have real world applications. If you want a book on architecture then get a book on architecture. K&R is about C.
- commandlinefan 7y ago> No website is as good as a good book Good (and often forgotten) advice for more than just C...
- Touche 7y agoI don't agree with this sentiment. People learn different ways. I personally learn through trial and error, and explanations of things that I haven't been able to "touch" yet don't help me at all.
- jasonjei 7y agoI like the K&R book, but I think what really taught me the most about C was actually writing programs in C. And playing around with particularly interesting features like function pointers and OS library interaction such as dynamic memory allocation.
- WoodenChair 7y ago> I don't agree with this sentiment. People learn different ways. I personally learn through trial and error, and explanations of things that I haven't been able to "touch" yet don't help me at all. Learning through trial and error can be okay for custom problems that don't have well defined solutions. For simple problems, it's highly inefficient. Extreme example: if I want to print something to the console in C, I can use trial and error for a half-hour to try to understand the nuances of how to use printf(), or I can read for a few minutes a few pages in a book or an (good) online tutorial. Not only will I learn faster, I will also learn best practices. My experience has been that people who are really against learning through books/tutorials tend to have short attention spans. Which is okay—books don't work for you. But for people who do have the ability to sit and read, it can be much more efficient than struggling through trial-and-error. Somebody has already solved your problems, and they can tell you in a few pages how you can solve them too.
- anaphor 7y ago"C Interfaces and Implementations" is another one that comes highly recommended. https://sites.google.com/site/cinterfacesimplementations/ https://sites.google.com/site/cinterfacesimplementations/
- sn9 7y agoThis book is fantastic to tackle for anyone comfortable with C at the level of K&R. A great second book on C. And one of the few examples of literate programming one might come across!
- ternaryoperator 7y agoIn the 90s, most seriouc C programmers knew about these books. They were the core books most devs relied on and referred to. They're all good. I disagree with this comment: "No website is as good as a good book. And no good book is as good as a disassembly output." There are many websites today that are excellent. And there are many websites that cover obscure topics not found in books. Finally, I think it's important to move past C89 to at least C99. I realize in 2011 (the date of this post), that was less feasible. But today, there is little reason for most projects not use the advances found in C99.
- imron 7y ago> But today, there is little reason for most projects not use the advances found in C99. Does visual studio support c99 yet? Last I heard MS wasn’t interested in supporting it.
- hazeii 7y agoReally? No longer an MS user but occasionally my code gets ported to Windows so would like to know more.
- dfox 7y agoMSVC in C mode is essentially C89 plus extensions needed to compile C++/C99-isms present in Windows SDK and DDK headers. And Microsoft seems to be mostly interested in whether the compiler is able to build NT kernel and drivers and nothing much else.
- nwellnhof 7y agoThat's not true for quite some time. Visual Studio 2013 added many C99 features that aren't in C++ like compound literals or designated initializers.
- flohofwoe 7y agoThe only notable C99 features not supported on the MSVC C compiler are: (a) VLAs, and (b) type-generic macros. The distinction between the MSVC C and C++ compiler is important though. The MSVC C++ compiler doesn't support any C99 features.
- fabiensanglard 7y agoI feel like I wrote that a decade ago. Wait. Damn. It WAS a decade ago. Amazingly the list is still relevant. I will try to check out the new suggestions on this thread.
- sandov 7y agoHave you read "C Programming: A modern approach" (2nd ed)? And if so, what do you think about it?
- wmwragg 7y agoI've found "Understanding and Using C Pointers" by Richard Reese, a really wonderful book.
- ExtremisAndy 7y agoSo glad to see this little gem mentioned! I have many books on C, but this is the only one I've ever read cover-to-cover. Clear and to the point, and no fluff/silliness. One of my favorite programming books ever!
- polyphonicist 7y agoHas your book recommendations changed in this decade? Would you recommend different books today?
- fabiensanglard 7y agoNo, I think these books are still a decent recipe for a good start. There are a few mentioned on this thread I have not read yet so maybe these will change my mind.
- pmiller2 7y agoInteresting comment they made about using C89 for portability. What's the state of C99 today? I know gcc doesn't support all C99 features, but what about other compilers? Is it worthwhile to use C99 in a new project?
- steveklabnik 7y agoVisual Studio is another one: https://stackoverflow.com/questions/48615184/does-visual-studio-2017-fully-support-c99 https://stackoverflow.com/questions/48615184/does-visual-stu...
- madmax96 7y agoI believe GCC does support all of C99 and has for a while. https://gcc.gnu.org/c99status.html https://gcc.gnu.org/c99status.html
- snazz 7y agoYou can safely use C11 or even C18 if you’re not too worried about support beyond Linux, macOS, and Windows with Clang. Game consoles and embedded development might require crappy old compilers that don’t support anything but C89, but otherwise use the latest version you can.
- quelsolaar 7y agoC99 is well supported now, but Its has become increasingly clear that some of the changes to the definition of undefined behavior in the spec has made som very troubling compiler optimizations possible that can make C a lot less dependable. Later versions of C also adopt a new memory model that is very broken. memcopy is for instance impossible to implement in C17. Due to these issues the Linux kernel is no longer using standrard C. So as it stands C89 remains a good choice.
- cesarb 7y ago> Due to these issues the Linux kernel is no longer using standrard C. The Linux kernel never used standard C, since the very first release (0.01) it already depended on GCC extensions.
- fao_ 7y agoIt's unfortunate he doesn't list the POSIX system interface, which has personally become an absolute boon: https://pubs.opengroup.org/onlinepubs/9699919799/ https://pubs.opengroup.org/onlinepubs/9699919799/ You can search it using duckduckgo with !posix, too. Something else I've found infinitely useful when digging into musl libc or doing assembly programming, is the SYSV x64 ABI: https://refspecs.linuxfoundation.org/elf/x86_64-SysV-psABI.pdf https://refspecs.linuxfoundation.org/elf/x86_64-SysV-psABI.p...
- chandlore 7y agoThanks for the link to the POSIX docs, looks very useful. More recent specs for the x64 ABI can be found at https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI
- kuharich 7y agoPrior discussion: https://news.ycombinator.com/item?id=11606296 https://news.ycombinator.com/item?id=11606296
- wwweston 7y agoOne of the things I tend to think about these days is return on investment. I spent several years at the beginning of my career being a bad and then mediocre C programmer, and once I found a few other languages, I got the sense that being a mediocre-to-good programmer in these languages would be much easier, and that seems to have been borne out. Late into a career investing in other areas, what's the advantage of becoming a good C programmer? Especially in a time where Rust and Go are viable options?
- jason0597 7y agoRust isn't viable for embedded platforms, at least not yet. It's not as easy to compile it to the most obscure ISAs as C, and the little support it has for stuff like STM32 is restricted to just that group of microcontrollers and doesn't support the entire ARM range. Maybe in the future? I'm looking forward to that day! Go is probably never going to run on microcontrollers due to its very big overhead. C perfectly matches on top of the hardware of a processor. Every single design decision about C was made with the computer in mind. Memory, pointers, stack, call stack, returns, arguments, just everything is so excellently designed. Even Linus Torvalds says so! https://www.youtube.com/watch?v=CYvJPra7Ebk https://www.youtube.com/watch?v=CYvJPra7Ebk If I were to make one change to C, it would be to completely rip out the #include system and bring a proper modules system. Apart from that, it's pretty much perfect.
- manfredo 7y ago> Go is probably never going to run on microcontrollers due to its very big overhead. My employer runs go on micro controllers. Definitely suboptimal, but as long as the cost of increasing hardware capacity to accommodate Go is feasible then it's a viable option.
- jason0597 7y agoIsn't it counter productive to go out of your way to find better hardware to fit your language choice? Why not choose a lighter language?
- AceJohnny2 7y agoThe K&R book was for decades my gold standard of a programming book. Perfectly clear and concise, its one notable failing being that it's obsolete. The Rust Programming Language [1] has since equalled and surpassed it in my mind. Hats off for Steve Klabnik & Carol Nichols :) (note, I'm not saying Rust is a better answer than Fabien's recommendation, just that its book is as high quality as the excellent K&R) [1] https://doc.rust-lang.org/book/ https://doc.rust-lang.org/book/
- Gibbon1 7y ago> I picked C89 instead of C99 Stopped reading right there.
- makecheck 7y agoUsing C as a lowest-common-denominator for game engines makes sense but I do love having Objective-C (despite the platform limitations). It just makes expressing game logic so easy, with protocols, etc. and I would not want to do it all with just C.
- matheusmoreira 7y ago> The Standard C Library > Or how errno came to existence? This is interesting. According to this book, errno was created because they wanted system calls to work like ordinary C functions: > Each implementation of UNIX adopts a simple method for indicating erroneous system calls. > Writing in assembly language, you typically test the carry indicator in the condition code. > That scheme is great for assembly language. It is less great for programs you write in C. > You can write a library of C-callable functions, one for each distinct system call. > You'd like each function return value to be the answer you request when making that particular system call. This turned out to be unnecessary. For example, many Linux system calls return a signed size_t type with either the result or the negated errno constant. When an error occurs, the C library stub function simply negates that value and assigns it to errno which is likely a thread-local variable. The C standard library provides many examples of bad design. All the hidden global data, the broken locale handling, the duplication found in so many str* and mem* functions... Freestanding C lacks most of the standard headers and is a better language for it. Understanding the historical context that contributed to these designs is very useful since it allows new languages to avoid repeating these mistakes.
- markus_zhang 7y agoI think for us laymen, the most difficult thing is to find a good reason to use C frequently. I have a few "legitimate" (in the sense that C is actually suitable for those) non-embedded projects that I'd like to take on in the future when I have time to pick up C: 1 - Recreate some of the Linux command line tools, including a command line interface similar to BASH; 2 - Implement a fully functional compiler or byte-code Virtual Machine for a stripped down scripting language; 3 - Write a key-value data store Sadly I really can't name any project that is not system programming. I saw some projects that use C for backend (CGI style?) programming or game programming but I believe there are more suitable tools for either of them. BTW I also found it very clear to use C or a stripped down version of C++ to teach myself Data structure.
- yters 7y agoC + knowing the Linux API and what is done in kernel vs user space can lead to very efficient Linux software. Since much consumer software these days is a webapp with a Linux backend, this sort of embedded optimization can make good consumer sense.
- markus_zhang 7y agoIt's a pity that it's almost impossible for a non programmer to find a C/C++ job nowadays. Much of the deeper knowledge takes too much time and effort to master from outside of the field so I guess most people don't go this way.
- mxschumacher 7y agoA lot of widely used recent CLIs have been implemented in Go or Rust, e.g. I don't think I would choose C for such a task these days. https://github.com/BurntSushi/ripgrep https://github.com/BurntSushi/ripgrep https://github.com/sharkdp/bat https://github.com/sharkdp/bat https://github.com/jesseduffield/lazydocker https://github.com/jesseduffield/lazydocker https://github.com/ogham/exa https://github.com/ogham/exa https://github.com/docker/cli https://github.com/docker/cli https://github.com/cli/cli https://github.com/cli/cli
- aungmyohtet 7y ago>> Expert C Programming . This book is fantastic because it will bring your attention to what happens under the hood in a very entertaining way. I am not a C programmer nor was trying to become one. Just trying to be familiar with low level programming and computer internals in general. But I enjoyed reading the book a lot. One of the the stories I remember is about the programming contest at Carnegie-Mellon University. The rules were simple that the program had to run as fast as possible and the program had to be written in Pascal or C. Here are some paragraphs extracted from the book about the result. “The actual results were very surprising. The fastest program, as reported by the operating system, took minus three seconds. That's right—the winner ran in a negative amount of time! The next fastest apparently took just a few milliseconds, while the entry in third place came in just under the expected 10 seconds. Obviously, some devious programming had taken place, but what and how? A detailed scrutiny of the winning programs eventually supplied the answer. The program that apparently ran backwards in time had taken advantage of the operating system. The programmer knew where the process control block was stored relative to the base of the stack. He crafted a pointer to access the process control block and overwrote the "CPU-time-used" field with a very high value. The operating system wasn't expecting CPU times that large, and it misinterpreted the very large positive number as a negative number under the two's complement scheme. “
- markus_zhang 7y agoThis reminds me of Mel the real programmer. I'll quote: Mel loved the RPC-4000 because he could optimize his code: that is, locate instructions on the drum so that just as one finished its job, the next would be just arriving at the “read head” and available for immediate execution. There was a program to do that job, an “optimizing assembler”, but Mel refused to use it.
- senderista 7y agoI would add "C Interfaces and Implementations" to his (excellent) list.
- LessDmesg 7y agoC, the low-level language that cannot even get integer types right and believes that -1 is greater than 1... I wish the Zig language people get some industrial backers so C can finally start fading away to obscurity.