Strongly complemented by Sedgewick's Algorithms in C.
[0] https://www.amazon.com/Interfaces-Implementations-Techniques...
https://www.amazon.com/Interfaces-Implementations-Techniques...
As mentioned in another post, David Hanson's "C Interfaces and Implementations - Techniques for Creating Reusable Software" [1] is a great book, stressing the design of good APIs. This book in particular might help you in your goal to become a better engineer.
On the free side, there's an excellent PDF by Jens Gustedt, "Modern C" [2]. I've not read the whole thing but it seems like an in-depth look at C11.
John Regehr's blog "Embedded in Academia" [3] is a good resource for C programming. You'll learn a lot about weird edge cases and undefined behavior. He also has a recent post about teaching C, with suggestions for resources [4].
[0] https://www.amazon.com/21st-Century-Tips-New-School/dp/14919...
[1] https://www.amazon.com/Interfaces-Implementations-Techniques...
[2] http://icube-icps.unistra.fr/img_auth.php/d/db/ModernC.pdf
(Regular HN readers will recognize the author of the top review on Amazon.)
[0] http://www.amazon.com/Interfaces-Implementations-Techniques-...
I also second the recommendation for Peter van der Linden's Expert C Programming for its masterful treatment of how C really functions, including the surprisingly frequent areas in which real-world constructs produce "undefined behavior" from the perspective of the C standard.
[1] http://www.amazon.com/Interfaces-Implementations-Techniques-...
The ability to create abstractions is pretty much a part of any programming language, including assembler. They're a property of the structure of the code, not of specific language features. For example, in the Linux kernel, which is written in C, there's an abstraction called a file descriptor that represents a stream of bytes that your program can read/write, whether it comes from a file on a disk, a serial port, a pipe, etc.
Interfaces also exist in all languages: they're just a well-defined set of calls that one piece of code uses to communicate with another piece of code. For example, the C runtime library (or any library) has an interface (API), and callers of the library don't need to know about the internal structure of the library to be able to call its services. (There's a pretty good book called "C Interfaces and Implementations"[1] that talks about how to write reusable code in C.)
Classes are also possible to implement in C. A class is pretty much a data structure with a bunch of functions (the methods) that manipulate its data. In C, this can be represented by a structure and bunch of function pointers. The "constructor" function calls malloc() to create an instance of the class, sets its member variables from its parameters and returns a pointer to it. (Implementing inheritance is a bit tricky.)
To be able effectively split development tasks across a team, the same rules apply as in any other language: implement functionality behind well-defined APIs so that one part of the code can be used by another without having to know the details of how it works.
http://www.amazon.com/Interfaces-Implementations-Techniques-...
It uses Donald Knuth's literate programming which takes getting used to, however, it's a great case study of how to make a good library.
There is a new book on "21st Century C" which I haven't read. It has mixed reviews, however.
http://www.amazon.com/21st-Century-Tips-New-School/dp/144932...
first is the classic Hanson book "C Interfaces and Implementations", http://www.amazon.com/Interfaces-Implementations-Techniques-... while you may not be coding in C the basic paradigms do carry over.
second is use the API a couple of times and you'll see natural cleavage points.
i generally develop APIs on paper first, which also helps me ensure consistency that is absent when i develop them too quickly or organically. i keep in mind my goals, i document as much as possible, and i try and stick to a paradigm.
hope that helps. i've written APIs used in internal services and applications but never externally, publicly available. i'm no expert but that's how i start.
I am confused by the implication of this code
var prices = new(Table, String, Int); put(prices, $(String, "Apple"), $(Int, 12)); Stack objects are created with "$" so these are on the stack and then placed into the Table? So if this was in a function and the function returned, the Table (lets assume it was global) would now be pointing to destroyed stack variables? Is that the correct interpretation?Is this all done with header files and the preprocessor? It looks like that is the case - if so, I am impressed at the dances you got it to do ;) Also, have you read http://www.amazon.com/Interfaces-Implementations-Techniques-... which does some "Object Orientation" in C tricks?
I picked it up after tptacek recommended it here on HN, and it's definitely worth every penny if you want to do any C programming on a reasonably sized project.
Why, there's even a whole book on that: http://www.amazon.com/Interfaces-Implementations-Techniques-...
Like Norvig's Paradigms of Artificial Intelligence: Case Studies in Common Lisp and Joshua Bloch's Effective Java, it's one of those books which despite having a specific programming language in the title, is really about programming in general.
C A Reference Manual http://www.amazon.com/Reference-Manual-Samuel-P-Harbison/dp/...
Expert C http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp...
C Interfaces and Implementations http://www.amazon.com/Interfaces-Implementations-Techniques-...
C Traps and Pitfalls http://www.amazon.com/C-Traps-Pitfalls-Andrew-Koenig/dp/0201...
http://www.amazon.com/Interfaces-Implementations-Techniques-...