The following books are in ascending order. That is, understanding the later books in the list is made vastly easier by first having understood the earlier books. The C programming language is certainly a good basis for learning other high-level languages whether it be C++, Java, Dylan,SmallTalk, or whatever. The major difference between C and these other languages is that they are object-oriented, a major benefit for large projects but, I believe, best approached having already had some success with smaller, procedural projects.
The classic book on the C language is The C Programming Language by Brian W. Kernighan & Dennis M. Ritchie, the creators of the C language. Although it purports to be teaching only a language, the book slyly uses gradually more complicated examples to teach important algorithms such as hashing and methodologies such as recursion. The chapter 'UNIX System Interface' can be safely skipped by Macintosh programmers.
For a more comprehensive treatment of algorithms and to see how much can be done with a subset of C, Algorithms in C by Robert Sedgewick works very well. This is the book for problems of the sort, "Given a set of points on a plane and a rectangle, find the subset of points that lie within the rectangle. Beyond presenting very useful algorithms cookbook-style, he gives very sound guidelines for selecting among different algorithms that accomplish the same thing. This book is also available as Algorithms in C++, although the differences are minor.
Once you move beyond algorithms and begin to present a user interface to exercise those algorithms intuitively, there is a need to hide some details and work with a program's entities abstractly. A starting point for object- oriented programming in C++ is The C++ Programming Language by Bjarne Stroustrup. Only in the last year or two have all of the language features described in this book been available in mainstream compilers. Stroustrup goes through all of the features of the C++ language before talking about the design and project management issues that led the evolution of C++ out of the C language.
Once you feel comfortable with the C++ language, you may feel a need to do more than write correct code. Designing the internal structure of a large project requires a different level of abstraction than balancing parentheses. The book, Object-Oriented Analysis and Design with Applications by Grady Booch, has an unwieldy title but directly addresses the way human cognition impacts design issues. A graphical notation for describing the an object-oriented design's entities and their relationships is presented. In the final section, that notation is used to design five applications. The first edition had its example code in a few different object-oriented languages while the second edition concentrates on C++. The first edition also came with a drawing template for the notation and far fewer typos than the second edition.
Since 'standing on the shoulders of giants' is preferable to 'reinventing the wheel' (sorry about those metaphors! B-> ), recycling of designs is much prized. The book Design Patterns, Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson & John Vlissides is devoted to finding common object-oriented usages. Further, they give names to these usages to create a design vocabulary.
There are many 'hints and tips' books but my favorite is Writing Solid Code by Steve McGuire. A former Microsoft developer and troubleshooter, Steve shares lots of hard-won advice for prevention and detection of bugs.