A few thoughts of my own, I'm a beginner C programmer, but a very experiences C# one and I've dabbled in C++ and Haskell too.
Malloc: watch out with this on embedded platforms, try to use the stack where possible, malloc can lead to heap fragmentation which is a problem when you don't have much RAM.
By value and by reference: this is a pain in C, I find myself looking towards C++ where you can delete the move and copy constructors (and so disable copying for a struct) if you want. Still you see a lot of
memcpy when it isn't always needed. IMO you should provide a copy function for any struct where there is any ambiguity (i.e. all of them).
K&R: probably not the best book to start with anymore, don't recommend it to beginners! There are things like assignments in if statements in there...
if ((sign = n) < 0)
n = -n;
(section 3.6 - 2nd edition)
C99: welcome to the future, it's only 17 years old now. Use it. GCC 4.4 that we use on the AVR32 supports it (and it's the default in the Makefiles).
Variable declaration: do it in the least scope possible, and initialise it at the same time. You don't need to declare them at the top of the function any more.
I flicked through 21st Century C to get myself up to speed, it's definitely aimed at people that already know a bit of C and how to use the command line. It has chapters on Makefiles and autotools which I appreciated.