16 ms·
Beej’s Guide to C Programming [pdf]
- tumblewit 5y agoFrom the creator of the famous Network programming in C guide.
- quyleanh 5y agoNice. But is there any like-this guide in Rust?
- RJIb8RBYxzAMX9u 5y agoThe Rust Programming Language[0] is the officially endorsed guide. I thought it was a good starting point. [0] https://doc.rust-lang.org/book/ https://doc.rust-lang.org/book/
- Flex247A 5y agoThank you for posting!
- blunte 5y agoIMO, pointers are less difficult to comprehend than other abstractions, like lambdas are. If you know how to walk down a street and stop at the right street number, then you have used pointers. And if you've ever observed that one tall building may "cover" a range of street numbers, such as 200-220, then you should understand how to move from one 4-byte "value" to the next in an array in memory. Anyway, many more analogies... probably better than this one. Maybe unions could make using pointers a bit more challenging, but again, tall buildings next to short buildings and so on. We do this kind of pointer calculation in real life.
- atoav 5y agoWhat pointers basically are is not particularly hard to grasp. What is harder to grasp it what can be done with them and how you can shoot yourself in the foot with them in non-obvious ways. I think I only understood much of it once I learned Rust, because you realize: Ah, that thing I once did in C is something that maybe ahouldn't be possible at all without extra steps. Even if I were to nwver use Rust again, this definitly helped to understand how to use pointers more safely.
- chasil 5y agoI think that pointers are a tool to control a CPU's indirect addressing modes from a higher-level language. Exposure to an assembler makes pointers easy to understand.
- qsort 5y agoWhat's difficult to understand about pointers isn't the concept of a pointer itself, or even * and &, it's the fact that working with pointers requires you to simultaneously understand different abstraction levels. While it's not unique to pointers, and it's in fact the case for most nontrivial programming tasks, what's unique about C is that pointers are so pervasive you can't really do anything if you don't understand how to work with them. IME languages like Python aren't any easier than C to work with (ignoring UB issues of course), but it's certainly the case that you can probably kinda sorta get your job done with Python even without understanding the first thing of what you're doing, and that's not happening if you write in C.
- bluetomcat 5y agoIn C, pointers require you to think deeply about the ownership and lifetime of any "allocated object" at runtime. How long does it live, who is responsible for the deallocation, how many pointers does your program hold to that object (dangling issues). Ultimately, it can lead to a cleaner design if these issues are taken seriously up-front.
- qsort 5y agoI don't disagree with that, but most cases fall within a pretty clear pattern: - typedef struct { ... } foo - foo *foo_create() - void foo_destroy(foo *) - a bunch of functions that take foo* as their first arg which is kind of the same as a class and only more error-prone. I say this as someone who actually _likes_ C, but the manual memory management model is very often unnecessary, confusing, repetitive. There was an idea some time ago of a language extension that would extend the concept of automatic storage duration to allow an explicit destructor to be called when the variable goes out of scope, like <close> variables in some languages. I genuinely think things like that would make the language a bit more ergonomic without fundamentally changing its nature.
- bluetomcat 5y agoThat's why I tend to always prefer automatic and static storage to dynamic allocation wherever possible, especially in cases where you don't have "N" items or "N" cannot possibly exceed a certain small value. Also, allocation/deallocation of the certain object need not be defined within its module. It should be up to the caller to decide whether to allocate the object on the stack, statically or dynamically depending on the caller's situation: foo f; foo_init(&f); foo_destroy(&f); ... foo *g = malloc(sizeof(foo)); foo_init(g); foo_destroy(g); free(g);
- cassepipe 5y agoPointers aren't that complicated but C syntax is misleading imho until someone comes along and tells you that the declaration syntax "follows use", which does not seem like the greatest idea. Then you get used to it and forget about it but when you don't know the principle behind declaration syntax, it does not help you reason about the language.
- young_unixer 5y agoYup. I spent a ton of time trying to make sense of pointer syntax (* operator/modifier), until I realized that it didn't really make sense (except for the simplest cases) and then I could get on my life.
- cassepipe 5y agoThere's actually a logic to it, although not an intuitive one at all, and it's that declaration should follow use. That is `int *ptr;` is a pointer to an int and to get the int you have to use * on it.
- jstimpfle 5y agoThe logic is that by declaring `int *ptr;` you effectively say that `*ptr` is an `int`. Only the first token (which must be a type) is syntactically special, the rest is normal expression syntax. Same goes for arrays, `int *x[30]` just says that `*x[30]` is an `int` (well, technically it's out of bounds by 1), thereby we're declaring an array of 30 int-pointers. Of course, that hasn't been entirely true since function declaration changed with ANSI C in the late 80s or so.
- kaba0 5y agoBut int-pointer is the type of it. It makes no sense that it “sticks” to the variable name.
- Koshkin 5y agoThe reason the asterisk naturally "sticks to" the name is simply the possibility to write a series of declarations like this: int a, *b, (*c)(int);
- ZoomZoomZoom 5y agoPointers seem easy until you understand the pointers you're working with do not correspond with the basic hardware model you have in mind: https://www.ralfj.de/blog/2018/07/24/pointers-and-bytes.html https://www.ralfj.de/blog/2018/07/24/pointers-and-bytes.html https://www.ralfj.de/blog/2020/12/14/provenance.html https://www.ralfj.de/blog/2020/12/14/provenance.html https://www.ralfj.de/blog/2019/07/14/uninit.html https://www.ralfj.de/blog/2019/07/14/uninit.html
- jhgb 5y ago> If you know how to walk down a street and stop at the right street number, then you have used pointers. And if you've ever observed that one tall building may "cover" a range of street numbers, such as 200-220 I see that as a European, I have virtually no chance to understand pointers using street numbers. :) (Fortunately I've never had problems either with lambdas or with pointers.)
- ricardobayes 5y agoLike my professor used to say, if you ever saw a pidgeon, you know what vectors are.
- mytailorisrich 5y agoC is an abstraction over assembly, really (benefits being that it is simpler by being more abstract and portable across CPU types). I've always thought that an introduction to CPUs (can take a simpler one as example) and how they work, how memory is (usually) organised, and to assembly would go a long way in helping understand many programming issues and C. My experience is that C or programming concepts are often taught in a very abstract/mathematical way, which can be hard to grasp compared to a more practical approach. If you take a concrete example where memory is effectively an array and indices are addresses (which holds true for most cases and, in any case is a good example) then understanding pointers becomes basically common sense and notations are simply conventions of the language you're using.
- Arch-TK 5y agoTreating C as an abstraction over assembly is a surefire way to step into all the thousands of sharp edges C has. In fact I would hazard a guess that the majority of bugs found in software written in C are a result of programmers treating it as a portable assembler instead of a language for programming an abstract machine. So many incorrect assumptions arise as a result of telling people to treat C as a portable assembler that I think it's safe to call it an extremely bad bit of advice.
- mytailorisrich 5y agoI was discussing pointers. I only commented in passing about C being portable over assembler. You could rephrase this as it being a language for programming an abstract machine and it would not change anything about my comment (nor would it change the fact that C is an abstraction over assembly) Thank you for your reply...
- Arch-TK 5y agoThe fact that you didn't use the term "portable assembler" when saying: "If you take a concrete example where memory is effectively an array and indices are addresses (which holds true for most cases and, in any case is a good example)" doesn't change the fact that the statement makes links to how actual machine memory operates on what you personally think is a usual machine. This is really not a good idea because it encourages people to think of pointers as all existing in the same place and encourages erroneous thinking such as subtracting two pointers to different objects or confusion surrounding why the numbers you get when you `int a; char b; printf("%p, %p\n%p, %p\n", &a, &a+1, &b, &b+1);` differ in separation. Also subtler errors arise such as people assuming that all pointer types are effectively equal as long as you convert back to the correct pointer type when it comes to using the pointer (really subtle issues like people assuming that you can convert `int *` to `void *` safely). The "very abstract" way C is taught actually prevents people from making such assumptions by not priming them to make them. The fact that people get complacent and start to lean on their understanding of (what they think are) real machines to write C is the result of the bugs I mentioned in the previous response.
- augustk 5y agoFor anyone who wants to learn about pointers I can recommend studying a language simpler than C like for instance Oberon where pointers are more restricted. Having a look at Oberon can also broaden your view even if you know pointers in C. https://www.miasap.se/obnc/oberon-report.html http://people.inf.ethz.ch/wirth/Oberon/PIO.pdf
- mumblemumble 5y agoPointers are like swazzles[1]. The construction is very simple. The principle behind how they work is very simple. Learning how to use one well enough that you can (a) consistently make it do what you want, and (b) not injure yourself in the process, though, is no mean feat. [1] https://www.atlasobscura.com/articles/swazzle-punch-and-judy https://www.atlasobscura.com/articles/swazzle-punch-and-judy
- chowells 5y agoWell, you've demonstrated that memory addresses aren't that hard. But you've also demonstrated how easy it is to get undefined behavior in C programs. C's pointers aren't memory addresses. Ok, they tend to be represented as such at run time, but that's not what the spec actually says the are. And as far as compiler authors are concerned, they can do anything they want as long as it's within spec. Further, the spec even requires some additional behaviors pure memory addresses aren't capable of. See https://www.ralfj.de/blog/2020/12/14/provenance.html https://www.ralfj.de/blog/2020/12/14/provenance.html for examples of the extra requirements. Compared to that mess, lambdas are trivial. They're just functions.
- aphrax 5y agoI've enjoyed this guide a number of times but each time I hit a brick wall trying to understand pointers. I'm still keen to learn but it just doesnt 'click' for me... Edit: poor grammar
- sanedigital 5y agoOne analogy I’ve used to teach pointers is to think of them as phone numbers. They’re an identifier used to get ahold of something that you might not otherwise know exactly where it is. If you call my number, I’ll pick up. But if I transfer my number to someone else, that doesn’t mean anything happened to me personally. That number is just not pointing to new anymore.
- unwind 5y agoThat is fascinating, thanks for sharing. What part of pointers is it that makes it so hard for you to grasp, if you have any thoughts? Do you have any experience in other programming languages? How familiar are you with low-level computer architecture, at the CPU/memory level? I guess one important part is to realize that in C, variables are basically names for memory locations, that in turn hold values. In other languages variables can be more abstract, and you have no idea how the value(s) are being associated with the variable name. I started writing an example here, but I ran out of time and it wasn't good enough. :) Sorry. EDIT: Now I've taken a loo at the relevant pages in the guide itself, and it seemed to explain the concepts very clearly and easily, so ... I'm not sure how to help. :)
- aphrax 5y agoThanks for this - I think you are on to something when you mention the low level architecture, on reflection this is where I need to fully understand the concepts - I'm messing around in this area with the usual (Nand to Tetris) type info/tutorials. I'll then come back to this manual I'm sure. Like I say - I've enjoyed it quite a bit. Its certainly me lacking - not the book!
- argvargc 5y ago
- DyslexicAtheist 5y agoit actually has working examples for all of the C library calls even math routines. Not sure if it's complete but it seems so. This seriously helps bridging the gap between man (2) pages and putting things into working code and only beef I have is that I didn't have it 25 years ago. Very cool.
- saagarjha 5y agoNit: most of the C library calls are in section 3; section 2 is system calls.
- DyslexicAtheist 5y agoyepp (me facepalm)
- beej71 5y agoIt's not complete... There are tons of functions in C11+. I'm whittling it away. Putting in the examples for all the calls--I stole that idea from The Turbo C Bible, a book I really loved back in the day... because of the examples.
- yrgulation 5y agoI commented this before on a previous post on one of beej’s guides: https://news.ycombinator.com/item?id=26100075 https://news.ycombinator.com/item?id=26100075 These tutorials are the gold standard of tutorials. I wish more content would be as straight to the point and easy to follow.
- caseyavila 5y ago> It’s especially insidious because once you grok pointers, they’re suddenly easy. But up until that moment, they’re slippery eels. I'm sort of a C beginner myself. I understand pointers, and I do remember they clicked in my mind suddenly. The moment before, I didn't understand at all. I also love the quirkiness of this guide. Definitely going to give this a read.
- andi999 5y agoDo you mean the general concept or like: a is a pointer to an array of functions which return pointers to functions which return ints and take double arrays as parameters. This somehow never really clicked (or actually it clicked and declicked somehow)
- caseyavila 5y agoFor me it was the practical understanding. I understood the concept of a pointer, but I wasn't confident in writing code that used that used them or (more importantly) reading code. I would see an asterisk, multiple asterisks, or ampersands, and would get confused with the code. I do think some of the issues I encountered had to do with the notation of pointers. The asterisk serving as a symbol to both declare a pointer variable and dereference one.
- jmiskovic 5y agoIf you always read from right to left (and put occasional braces for readability) you can get through anything. Most tricky ones are in job interviews, while ones found in the wild will often make use of typedefs to break down the complexity.
- signa11 5y agoJens Gustedt's "Modern C" (https://modernc.gforge.inria.fr https://modernc.gforge.inria.fr) is an excellent resource as well.
- k_sze 5y agoJens Gustedt is a co-editor of the ISO C standard, so he knows his shit. Modern C is probably the best book about modern C, short of reading the standard.
- SAI_Peregrinus 5y agoIt's far easier to read than the standard, too, since it's explanatory rather than declaratory. The standard tells you what C can do, Modern C teaches you how.
- gnuvince 5y agoWhat does "modern" C imply? AFAIK, there are not very many new language features; is it about organizing code differently than what one would learn from K&R?
- ashconnor 5y agoC99 I would imagine: https://en.wikipedia.org/wiki/C99 https://en.wikipedia.org/wiki/C99
- unwind 5y agoThe current standard is C17, of course: https://en.m.wikipedia.org/wiki/C17_(C_standard_revision) https://en.m.wikipedia.org/wiki/C17_(C_standard_revision).
- mumblemumble 5y agoAccording to the introduction of the book, C17. Which is mostly just bugfixes on C11. But, compared to c99, you get nice things like generic expressions, better unicode, and (standard) multithreading.
- transient_47 5y agoI stumbled upon this gem a while ago [0] while looking for a decent tutorial and reference to C: Stuff that should be avoided: [...] Beej's Guide to C: http://beej.us/guide/bgc/output/html/singlepage/bgc.html http://beej.us/guide/bgc/output/html/singlepage/bgc.html Full of mistakes. [...] Could someone confirm this? I've seen a lot of threads here on HN praising beej's guides so I am somewhat confused. [0] http://www.iso-9899.info/wiki/Main_Page http://www.iso-9899.info/wiki/Main_Page edit: Formatting
- determinateproc 5y agoBeej himself lists this as an 'alpha-quality document' on the download page [0] and if I remember correctly, it has been so for years. Wonder why this is posted here on HN. [0]: http://www.beej.us/guide/bgc/ http://www.beej.us/guide/bgc/
- petee 5y agoI think posts like this are handy just for the extra exposure an alpha document might need; there's a lot of good feedback and discussion here that hopefully beej comes across someday and can finish the book
- determinateproc 5y agoOn further observation the git repository of the book [0] seems to be quite active. Maybe this book might be finished after all. [0]: https://github.com/beejjorgensen/bgc https://github.com/beejjorgensen/bgc
- beej71 5y agoBackstory: I started writing this book for novice programmers about 15 years ago. It was going to be a lot shorter. But I became disinterested because: 1. Most beginning programmers don't start with C 2. I wouldn't get a chance to go deep and explore the language. So I shelved it, unfinished. Flash forward to about a year ago... I had flash of inspiration: change the audience to intermediate programmers. Now I could skim the general conceptual stuff and get into more details. One thing, though. C actually added a lot of stuff in the intervening years. I didn't realize the magnitude of the project. Oh well! Too late to turn back now!
- exceltior 5y agoThanks for sharing this
- qwerty456127 5y agoAgain, the string chapter is telling us about zero-terminated char arrays/pointers and doesn't even mention Unicode/UTF-8 or safety :-(
- beej71 5y agoI do have a chapter on Unicode and wide characters, but it's separate from the "classic" strings chapter. That said, I could certainly refer forward to it. And C11 only has minimal portable UTF-8 support, but I do talk about it. I think C21 will improve on that a bit. A note on safety would be well worth it. I'll do that. Good suggestion.
- qwerty456127 5y agoCool. Thank you. Lack of coverage of this subject in educational materials has been pain ever since I was studied C at school. All the books said that: strings are zero-terminated char arrays. But this kind of strings is almost useless in today globalized world. Sorry I didn't notice you cover this topic in a separate chapter. This makes your guide really great. Let me suggest you mention that chapter in the strings chapter unless you have a reason to omit such a reference. Thank you for a great job!
- deleted 5y ago[deleted]
- emilengler 5y agoA thing I really enjoy about this guide is that it’s close to common C paradigms and practices. Many guides lack this and only show outdated ones.
- throws23577 5y agoI haven't read these 2 books, but would like the opinion of someone who did. [1] C Interfaces and Implementations: Techniques for Creating Reusable Software by David Hanson - HN's tptacek seemed to rave about this book, that's how I heard of it. Wonder what he thinks of it in 2021. [2] C Programming: A Modern Approach by K. N. King - this one seems to be loved by many. Seems to be more 'beginner-friendly' than the 1st one I guess.
- ZoomZoomZoom 5y agoYou can always check reviews published by ACCU.org: K. N. King "C Programming": https://accu.org/bookreviews/1999/graham_1260/ https://accu.org/bookreviews/1999/graham_1260/ Ben Klemens "21st Century C": https://accu.org/bookreviews/2016/demin_1882/ https://accu.org/bookreviews/2016/demin_1882/ Robert C. Seacord "Effective C": https://accu.org/bookreviews/2020/glassborow_1952/ https://accu.org/bookreviews/2020/glassborow_1952/ https://accu.org/bookreviews/2021/bruntlett_1959/ https://accu.org/bookreviews/2021/bruntlett_1959/
- throws23577 5y agoWow I never heard of Robert Seacord's 'effective C'. Thank you. Edit: Here's a short rationale for the book by the author. https://ieeexplore.ieee.org/document/9237323 https://ieeexplore.ieee.org/document/9237323
- tptacek 5y agoIt remains my favorite C book, though: I don't think you should write much C anymore.
- mrslave 5y agoMy favorite is Expert C Programming: Deep C Secrets by Peter van der Linden. I started it as soon as I encountered C at university and could only get through about a chapter at a time. By third year when the assignments in C got hard I was in a great position, partly for this book. Even crazier is I enjoyed it.
- dimran 5y agoThis is a wonderful book if you want to understand how the OSI model of internet works, clearly illustrated network apis. Man this book was amazing.
- cpach 5y agoI think you’re confusing it with another book. This is a guide to C programming. You’re probably thinking of Beej's Guide to Network Programming :) https://beej.us/guide/bgnet/ https://beej.us/guide/bgnet/
- mnunez 5y agoJust found out that it has an actively maintained GitHub repository, with 35 or more commits this April alone. https://github.com/beejjorgensen/bgc/commits/main https://github.com/beejjorgensen/bgc/commits/main
- dcchambers 5y agoBeej's Guide to Network Programming helped me survive a grad-level computer networking class as a naive undergrad in college. If his guide to C is anywhere near as good it should be an awesome resource.
- beej71 5y agoThe C Guide is still rough around the edges (and even some in the center). But I'm working on it! :-)
- billfruit 5y agoThere was a "C Unleashed" book, a massive tome of 1000+ pages written by many famous programmers, many of them who where quite active in comp.lang.c, like Richard Heathfield and CB Falconer, had quite insightful material in it. Any one remember the heyday of comp.lang.c? I wonder what goes on in there now.
- mistertester 5y agoYes, usenet was huge for me back in the early 90s when I had questions on C programming. I would ask them on comp.programming.c and had some of the best programmers providing guidance. Of course they were strict with questions/discussions being specific to ANSI C.
- beej71 5y agoI bought that book ages ago. Good stuff. comp.lang.c still has a small group of knowledgeable regulars, but a lot of the "old guard" seems to have stepped away. And Usenet is a shadow of its former self, obviously. Reddit has more traffic nowadays.
- deleted 5y ago[deleted]
- bluedino 5y ago#c on EFnet!
- ben_pfaff 5y agoI wasn't sure anyone but the authors remembered C Unleashed! I wrote the chapter on binary search trees and balanced trees. Comp.lang.c was important to me for many years. I've met 5 or so of the regulars at least once. The most famous comp.lang.c regular is probably Tim Hockin of the Kubernetes project.
- billfruit 5y agoThanks very much! The code from the book proved very useful since C does not have a standard library of rich data structures.
- rubicon33 5y agoI love Beej’s guide to network programming. Back when I was just starting to learn to code, I wanted to get right down to the low level C stuff and his guide was what I used. It was simple and approachable and I had a running TCP client by the end of the day. It was a thrilling experience for a young novice.
- Spivak 5y agoIs there any guide that operates at the level of the C abstract machine and a real platform because it's always really jarring to have lots of hand-wavy statements like > When compiling C,machine codeis generated. This is the 1s and 0s that can be executed directly by the CPU. No! Tell me about how the code is translated into an ELF executable, linked, has its memory laid out by the OS and then executed. > I’m seriously oversimplifying how modern memory works, here. But the mental model works, so please forgive me No! Tell me about how memory works in the C abstract machine which is what you can actually program against and guaranteed by the compiler. > Nothing of yours gets called before main(). In the case of our example, this works fine since all we want to do is print a line and exit No! tell that main is special because it's mapped to the _start symbol or at least eventually jumped into by code at that symbol which has an address that's stored by the linker in e_entry. Like I might be the weird one but this kind of writing (which is common to seemingly all C texts) confuses me more than if it had just been explained.
- 3rly 5y agoI see a lot of people making opinions that clearly shows that they have not audited the entire guide. For the intended audience that the author wanted to reach. I will say that he accomplished it. For anything that one finds as mistakes, the author went out of his way (via references) for the reader to dig further.
- dang 5y agoIt doesn't do the brisk business of the networking one, but there have been at least a couple past threads: Beej's Guide to C Programming - https://news.ycombinator.com/item?id=26100391 https://news.ycombinator.com/item?id=26100391 - Feb 2021 (1 comment) Beej's Guide to C Programming (2007) - https://news.ycombinator.com/item?id=15198093 https://news.ycombinator.com/item?id=15198093 - Sept 2017 (79 comments) As long as we're talking C programming, I'd single out this large thread with C Standards committee members from last year: Tell HN: C Experts Panel – Ask us anything about C - https://news.ycombinator.com/item?id=22865357 https://news.ycombinator.com/item?id=22865357 - April 2020 (962 comments)
- enahs-sf 5y agoI love C programming. Even though people say it's dangerous and easy to shoot yourself in the foot, It really is the simplest and most elegant way forward. That said, having to invent the wheel yourself so much, it is not as time efficient as some more modern languages. I liken it to an artisanal craftsman's tool versus a modern multi-tool like a dremel which would be something like python.
- seibelj 5y agoTotally agree - sometimes I solve small problems in C rather than a scripting language. It feels like freedom and the result is so damn fast.