Throughout my career, I've viewed C as the sleeping monster that mere mortals such as myself dare not waken. However, as I increasingly seek to achieve more complex goals in my projects, I find myself encountering C libraries (such as GMime) which will answer all my questions, if I could actually program in C. I have a copy of C Primer Plus Fifth Edition at hand, a development FreeBSD server as well as my Mac, but would like to ask of this community if they are aware of any other references, such as old CS course materials, which may help. Many thanks in advance. I realise that this is a long term goal, but feel that with my taste in server platform and operations software, C will prove a boon to me.
[+] [-] rsheridan6|17 years ago|reply
Books by W. Richard Stevens were old when I was learning, and older now, but they were the best guides to taking it to the next levels. You can pick up a lot of tricks and stylistic pointers from him while learning about UNIX features and networking. Maybe somebody will chime in with a more up-to-date resource that does the same thing.
[+] [-] screwperman|17 years ago|reply
This is an odd little book. It's frequently mistaken for an introductory programming book, which inevitably leads to frustration. It's not a good way to learn how to program; it expects that you're already familiar with machine architecture, assembly language, compilers, and at least one other high-level language.
It's not even a very good way to learn C. The idioms and best-practices for C programming have evolved substantially, even since the second edition was published, and some of the code samples look a bit dated.
As the parent said, you'll appreciate C only if you learn about machine architecture and Unix. Diving into a large codebase will get you acquainted with "modern" C.
I've found the book C Traps and Pitfalls to be the book to get you to think like a C programmer. The C Puzzle Book is pretty good for exercises, and Expert C Programming does a good job exposing the ugly side of C.
[+] [-] davidmathers|17 years ago|reply
This is key advice. Understand hardware first and pointers are obvious, don't and they are (apparently) confounding.
[+] [-] mlLK|17 years ago|reply
[+] [-] xenoterracide|17 years ago|reply
[+] [-] tumult|17 years ago|reply
I don't know what people are using to learn C these days, but the standard has always been the white book http://www.amazon.com/Programming-Language-Prentice-Hall-Sof...
You will find yourself spending more time thinking about programming concepts rather than dealing with C syntax, since it's pretty concise. I don't know how difficult it is to learn about pointers if you have already been programming for a while but haven't had to use references directly, but it's very important to learn. C does not do too much for you on its own, so handling references yourself is an important skill. It will also help you understand how higher level languages and concepts work.
If you are working through it and find that you're enjoying yourself, congratulations, you're a programmer :] Then it's time to pick up the 1st volume of Knuth and start working through that.
[+] [-] baguasquirrel|17 years ago|reply
1. naming conventions. I don't know why C programmers use the strange names that they do.
2. macros. C macros are a pain to read and follow.
I hope things will be easier to learn if you know this going in, because that's really all there is to it.
The catch with C is that while it is simple, writing good code with it is not. You have two tools for metaprogramming: macros and function pointers. C++ classes seem evil, until you see what people do in C in the absense of any mechanism for polymorphism.
Thankfully for you, you probably will only ever need to deal with libraries, not applications, so you'll never have to deal with the hell that comes with trying to use C for higher level work.
[+] [-] mahmud|17 years ago|reply
Most other C books will just treat it as a stepping stone for C++ which is a different beast, and a few awful offenders will stretch it to Java!
To see a few Algorithm implementations in C, there is no better friend than Robert Sedgwich's polyglot tome; it's the applied Knuth volumes that everyone keeps on their desk (quickly swapped for the actual Knuth volumes when expecting hacker guests.)
Along with C materials you will also need Unix materials. The two are inseparable and fuel each other. You already have a decent Unix in your Mac, and your FreeBSD is the best of the Unix breed bearing the original blood. For that there are no better companions than the books by Richard Stevens, both for system and network programming.
For larger scale software engineering you will need a few small to mid projects of your own. You will deal with header file and Make dependency problems, a few unix and processor portability problems and a few other stuff. The solution to those problems along with a fat library of useful routines are found in "C Interfaces and Implementations" by Hanson. It's a literate programming text where source code is interwoven with prose documentation and it's very self evident.
Along with productive C programming you might need to look into the darker side of C and Unix and follow the papers of the hacking underground (yes, HACKING, dispute the terminology all you want, but I think some blackhats deserve the noble noun more than javascript and CSS jockeys.) Unix and C have plenty of Not-TODOs to motivate plenty of caution. Hoglun and McGraw's Exploiting Software is the canonical C-Do-Not text books.
If you want to read library source code, your FreeBSD source code should give you plenty to keep you busy. Start with the sources for the games; I spent an enjoyable summer porting Minix games to DOS and taught me allot. There is also "The Standard Function Library", or SFL, google it, it has the cleanest C sources you ever seen. Highly recommended.
And should you ever want to write a C compiler, like I attempted, here is some advice: implement Oberon instead. Everything you could possibly learn at 1/100th of the headache.
Just the 2 cents of a guy who will only write C code again if there was a gun to his head ;-)
[+] [-] jussij|17 years ago|reply
That's the book I used to teach myself C and I though it was just brilliant.
[+] [-] FiveFiftyOne|17 years ago|reply
[+] [-] neilc|17 years ago|reply
Thankfully, C is straightforward to learn. The major concept you need to understand is pointers; once you've done that, there are some syntactic oddities to absorb (typedefs, function pointer syntax, arrays vs. pointers), and you should skim through the standard library (which is tiny compared to Java, or even C++), and you're most of the way there.
In addition to K&R, I've hears that Steele and Harbison's "C: A Reference Manual" is very good, although I haven't read it personally.
[+] [-] dnewcome|17 years ago|reply
[+] [-] cschep|17 years ago|reply
http://www.stanford.edu/class/cs107/
You can find the lectures on academicearth.org, or on iTunesU if you prefer to download them that way.
Jerry Cain is a great lecturer. I wish they'd post the assignments with the files they provide the students though. Maybe someday.
[+] [-] natrius|17 years ago|reply
http://academicearth.org/courses/programming-paradigms
[+] [-] sqs|17 years ago|reply
[+] [-] kmavm|17 years ago|reply
K&R et al. are fine, but I'm a particular fan of two slightly oddball, but great, books about C:
1. van der Linden's Deep C Secrets. Short of implementing a C compiler yourself, reading this book is the surest path to completely understanding some aspects of the C linkage model, and the distinction between arrays and pointers. It's also entertainingly written, which always helps.
2. The Lions Book, an annotated source listing for the Unix v6 kernel. The subject matter is one of the most beautiful and influential programs ever written. This ~10k-line program is completely understandable in six weeks' study, a couple months' tops, yet it staked out almost all of the abstractions that still underly modern operating systems. It is also C's native environment: C was literally invented to write this program. And while it's dated in some of its peculiarities ("=+" where we'd write "+=", identifiers only being significant in the first 8 characters, no typedef yet, a lot more reliance on the register keyword, etc.), it's damned fine code, by any standard. Each page brims over with good, informed engineering trade-offs; the sweet spot may have shifted since the days of 128k core and 16-bit CPUs, but the thinking that goes into those trade-offs is mostly unchanged.
[+] [-] twopoint718|17 years ago|reply
I made the most progress in C when I took a class on OSs. Mainly, we wrote systems programming sorts of things like a simple shell, our own version of malloc, a simple user-space thread library, and so on. This really gave me insight into how these things would be done for real. Also, writing something really linked-list-heavy gets you a feel for pointers really quickly.
[1]: I have K&R ANSI C and I found it very concise and well-written. It is probably one step up from the "raw newbie" class of books in terms of difficulty, but should feel just right for someone already acquainted with (an) other language(s).
[+] [-] antirez|17 years ago|reply
[+] [-] tptacek|17 years ago|reply
You should definitely learn C:
* You'll learn the memory hierarchy, which is probably the most important thing to know about performant software.
* You'll get 100x better at debugging --- both because you'll have practice, and because most of the tools you use to debug C code work for higher-level languages (gdb is still a better Ruby debugger than Ruby's own debugger).
* You'll be able to bridge Python (or Perl) to almost any library or framework you ever need.
2. In Which I Express Reservations
Don't learn assembly. In my (C and assembly-heavy) career, I've found it works in exactly the opposite direction: you won't really understand assembly until you understand C code. There are mainstream architectures (SPARC and MIPS) that are literally designed as drivers for C compilers.
You'll eventually want to be conversant in assembly so that you can debug faster (when it comes to the runtime, the C language is a flimsy abstraction indeed). But you should let your needs and interests drag you into the machine, just like you should probably learn "Stairway" and "Smoke On The Water" before mastering barre chords and sight reading --- you can have a pretty excellent punk band without ever knowing how to read music.
3. There Are Books
Everyone is going to have an opinion about K&R. What I think you need to know is, it's short and it's dry. I re-read it 6 years into my career and I was surprised at how rich it was; there's a lot of design and data structures material, beyond the core language.
There's a C book that changed my life. It's David Hanson's "C Interfaces And Implementations" (CII). I will now make a case for why it's the first and only book you'll need. You're coming to C from a high-level language. That language is giving you a couple key things you don't realize you depend on:
* Garbage collection
* Lists and hash tables
* Resizeable strings
Almost every major C project contains a site-specific reimplementation of these concepts. CII gives you one --- an internally consistent one, relatively well implemented, and extremely well documented. In doing so, it also teaches you the single most important thing about writing good C programs, which is how to build abstractions around your gnarly code.
The difference between people who know C as a language and people who can actually deliver software in it is resizeable containers (linked lists, dynamic memory allocation, high-level strings, doesn't really matter what the specific is).
The other book you want is "Advanced Programming In The Unix Environment" (or its moral equivalent, "Win32 Programming").
CII is "how". APUE is "what".
Finally, I like (for new programmers) "The Practice Of Programming".
4. What I Did To Get Started
I "knew" C for a while (maybe since I was 13) before I actually started coding in it. Two things got me unstuck.
First, I picked a couple basic Unix APIs and wrote little toy programs around them. If I remember correctly, the first thing I wrote was "who", from "getpwnam(3)", which forced me to do some basic strings and structure pointers.
Second, I wrote network code from a socket tutorial. Sockets are a great thing to get started on; just write a scraper for a service you like, and there's a zillion little problems you'll have to solve that are the same problems you solve in every other program you write.
[+] [-] jdybnis|17 years ago|reply
x86 is a convoluted horror. A lot of it makes no sense except in the context of backwards compatibility, which the documentation won't necessarily point out. I highly recommend picking up a microcontroller to learn on instead of a microprocessor. Microcontrollers are mostly self-contained systems, while microprocessors are just a small piece of the picture and have complicated interfaces to the rest of the system components.
I recommend picking something in the Freescale 68HC* family. The addressing modes and instruction set are fairly clean and the architecture is simple. Something based on ARM would probably also be straightforward to learn. Don't worry about choosing a 32 bit chip, 8 or 16 bit is fine. 8 and 16 bit chips are typically simpler and will still teach you the important concepts.
Spend a couple of weeks on this and your understanding of C will be easier to come by and more thorough.
[+] [-] wooby|17 years ago|reply
2. "The Unix Programming Environment" (http://www.amazon.com/Unix-Programming-Environment-Prentice-...) This is a recent find, but covers more application. It's almost a Part 2 of K&R and covers building problems and the Unix signal and file APIs. The examples are in an ancient syntax, but part of the fun is coding them and getting them to compile.
3. "The C Puzzle Book" (http://www.amazon.com/Puzzle-Book-Alan-R-Feuer/dp/0201604612) I found this one day at Fry's, and it's fucking awesome. You can effectively learn C using it without a compiler.
Good luck!
[+] [-] makecheck|17 years ago|reply
[+] [-] astine|17 years ago|reply
I don't use C much anymore (haven't since Highschool.) When I do, it's with GCC and I and the environment is still the hardest part.
Moral of the story being that C is pretty easy. I learned it with some very basic references. The hard part, supposedly, is pointers, and those are much harder to use than to understand. Basically, everything is done through them, without the usual abstractions that you would get with say, Java. You mainly just have to make sure you always have the right number of asterisks and ampersands.
One book I can suggest is Advanced Programming in the UNIX Environment by W. Richard Stevens, (revised version) which gives a very through introduction to UNIX from a C perspective. C is interesting in that it is almost a different language depending on which system you write it on and you'll spend more time learning system calls and UNIX paradigms than C syntax and pointers.
[+] [-] avinashv|17 years ago|reply
* Everyone is going to recommend K&R, which is fine. Find a copy of C Interfaces and Implementations as well--very good implementations with explanations of standard high-level structures.
* Read source. SQLite's source, for example, is very well written and documented, and they actually have a version to download recommended for reading (everything is in one file).
* Implement. You're going to want to try implement standard Unix commands yourself. Try writing an interpreter/compiler as well. These things give you a good grip on a wide variety of C basics and will make sure you can work well with memory management and all that.
* Assembly. This is where I would learn assembly (i.e., where I did). I don't think you need to go too far in depth, but a basic working knowledge will make debugging much, much easier.
[+] [-] hello_moto|17 years ago|reply
[+] [-] silentbicycle|17 years ago|reply
[+] [-] radu_floricica|17 years ago|reply
Like rsheridan6 said, assembly helps. It's not necessary though, as long as you realize a pointer is actually a memory address and not something abstract like a reference in Java or PHP.
[+] [-] davidw|17 years ago|reply
[+] [-] voberoi|17 years ago|reply
I became incredibly comfortable with C -- memory management, handling pointers, having a very clear picture of how types are represented in memory -- after taking that course. The lecturer (Jerry Cain) is fantastic as well.
The course changed this year so I don't have any thoughts on the current CS107 offering if you plan on taking it through their online course offerings for pay. The lectures, syllabus, and materials on Stanford Engineering Everywhere (OpenCourseWare at Stanford) are all from the course I took two years ago.
[+] [-] SwellJoe|17 years ago|reply
My book recommendations would be K&R, Advanced Programming in the UNIX Environment by Stevens, and C: A Reference Manual by Harbison and Steele. In that order. With liberal doses of web research and reading real world examples and experimentation.
[+] [-] miles|17 years ago|reply
http://tinyapps.org/weblog/misc/200904120715_learn_c_for_fre...
[+] [-] plinkplonk|17 years ago|reply
Work through, in order, (1) K & R (2) C interfaces and Implementations by David Hanson (3) Deep C Secrets by Peter Van der Linden (4) Advanced Programming in the Unix environment
Good Luck!
[+] [-] spc476|17 years ago|reply
[+] [-] JeremyChase|17 years ago|reply
While K&R is great, my copy is far less used than Pointers on C by Ken Reek. If you can find a cheap copy I highly recommend it. If you are working through K&R make sure to do each of the sample problems. The text is just the support to let you figure out how to do them.