HN Books @HNBooksMonth

The best books of Hacker News.

Hacker News Comments on
C Interfaces and Implementations: Techniques for Creating Reusable Software

David Hanson · 18 HN comments
HN Books has aggregated all Hacker News stories and comments that mention "C Interfaces and Implementations: Techniques for Creating Reusable Software" by David Hanson.
View on Amazon [↗]
HN Books may receive an affiliate commission when you make purchases on sites after clicking through links on this page.
Amazon Summary
creating reusable software modules; they are the building blocks of large, reliable applications. Unlike some modern object-oriented languages, C provides little linguistic support or motivation for creating reusable application programming interfaces (APIs). While most C programmers use APIs and the libraries that implement them in almost every application they write, relatively few programmers create and disseminate new, widely applicable APIs. C Interfaces and Implementations shows how to create reusable APIs using interface-based design, a language-independent methodology that separates interfaces from their implementations. This methodology is explained by example. The author describes in detail 24 interfaces and their implementations, providing the reader with a thorough understanding of this design approach. Features of C Interfaces and Implementations: * Concise interface descriptions that comprise a reference manual for programmers interested in using the interfaces. * A guided tour of the code that implements each chapters interface tp help those modifying or extending an interface or designing related interfaces. * In-depth focus on algorithm engineering: how to packag
HN Books Rankings

Hacker News Stories and Comments

All the comments and stories posted to Hacker News that reference this book.
Over the years, I have acquired most of what people call seminal C books, and after reading them, I recommend the following two books to people who already know programming:

Peter A. Darnell and Philip E. Margolis C - A Software Engineering Approach (3rd ed.) https://www.amazon.com/Software-Engineering-Approach-Peter-D...

David Hanson C Interfaces and Implementations: Techniques for Creating Reusable Software (!st ed.) https://www.amazon.com/Interfaces-Implementations-Techniques...

The first is clearly written and focuses on ANSI C (lexis, syntax and semantics), with a healthy dose of software engineering education along the way, which you may already have. (It does not yet cover the latest ISO changes.)

The second book is a true gem that teaches even seasoned programmers how to implement correct, clean and portable components as libraries in ISO C, with plenty of source code to show how the true masters of the language craft the finest code you can in C. Most books how fragments of linked list implementations, but only this book shows complete a whole range of important ADTs you cannot live without (e.g. List, Ring, Atom) in C portably, with strong typing, bullet-proof error handling etc. (Hanson is also the author of lcc, a portable C compiler.)

I'm actually surprised that these are both are so little known, and that the second one hasn't seen more editions.

chubot
I read the Hanson book ~10 years ago (he was briefly a coworker). It's interesting, and maybe worth checking out for experienced programmers, but NOT for someone who wants to learn C in 2022 and be productive.

The style doesn't match any C code you're likely to see. It basically presenting an STL-like set of data structures and standard library in C, not C++.

That style of programming isn't idiomatic in C. One thing that took me a long time to realize is that C is NOT a modular language! The best way to use C is to roll your own (or copy and paste) data structures for your problem, not try to use canned ones!

If you want the latter approach, C++ is better. It has better support for type safety, abstraction, and modularity (at great cost).

i.e. if you compare code of commonly used codebases like Lua, CPython, sqlite, Redis, BSD kernels, Linux, etc. you will see patterns, and they don't look anything like Hanson's book

adalacelove
> The best way to use C is to roll your own (or copy and paste) data structures for your problem, not try to use canned ones!

I committed atrocities until I realized this. C is not suitable for generic programming.

chubot
Yup, same!

And I just looked it up -- C was invented BEFORE abstract data types were! This explains a lot.

Programmers think "hash table", stack, queue, set, etc. are "the way you program", because that's how it's taught in CS 101. It's also asked a lot in interview questions.

But that line of thinking was invented AFTER C. I recall that Liskov did foundational work on ADTs, and Wikipedia agrees

Programming with abstract data types (Liskov and Zilles, 1974)

https://dl.acm.org/doi/10.1145/942572.807045

i.e. the origin of abstract data types is in this work on the CLU language.

Her 2008 Turing Award cites this work: https://amturing.acm.org/award_winners/liskov_1108679.cfm

At MIT she led the design and implementation of the CLU programming language, which emphasized the notions of modular programming, data abstraction, and polymorphism

-----

Meanwhile C was developed around 1972-73 to make the Unix kernel portable. It's a minimal layer meant to generate machine different machine instructions that will work on machines; it doesn't feature strong abstraction.

So what Hanson was trying to do is to add abstraction to C, but you need a language more like CLU or C++ to do that. Arguably Bjarne was "doing it right" -- actually changing the language.

----

HOWEVER I also had a recent experience that vividly shows the folly of ADTs even in C++, a language designed for them.

In C++, unordered_set<void star>::insert() is shockingly slow -- slower than malloc(1) !!! And it is slow BY THE SPEC. Because of the abstract operations that the C++ standard requires (e.g. iterators and invalidation), you have to use a slow closed-addressing/linked list implementation that allocates for EVERY element !!!

I hit this when working on the garbage collector for https://www.oilshell.org/ -- we're making a fork() friendly collector (no intrusive mark bits) that works with arbitrary addresses returned by malloc.

It made some of our benchmarks 10x slower in TOTAL runtime!

Best comment I found that explains it:

https://old.reddit.com/r/programming/comments/5pwgtn/hash_ma...

Chrome message from 2017:

https://groups.google.com/a/chromium.org/g/chromium-dev/c/rd...

So basically the hash table in C++ is a shockingly bad default, and it has to with a bad ADT design.

Doing ADTs in C is even worse. Hanson's book is more like a thought experiment in merging two distinct lines of thinking -- not something you should actually use and base your code on!!

----

This would be a good blog post -- I would title it something like C Was Invented Before ADTs, and C++ Isn't Great Either

pjmlp
I am quite sure JOVIAL, ESPOL/NEWP, ALGOL and PL/I dialects, Lisp, which predated C in more than a decade have enough abstraction capabilities, even by their state in 1972.
chubot
citation needed

We're talking about abstract data types

Common Lisp yes, and its research predecessors, but not Lisp in 1972

CLU itself was based on Algol, and influenced C++

pjmlp
This tiring requests for citations...

DEFINE STRUCTURE + type functions + function/procedures is all one needs in PL/I to achieve similar workflow,

https://www.ibm.com/docs/en/epfz/5.1 (No earlier online version found)

And if you want to read PL/I documentation that uses the term "abstract data types",

https://www.ibm.com/docs/en/z-netview/5.4.0?topic=SSZJDU_5.4...

Interlisp initially created in 1970, besides the lists everyone knows, introduced atoms, string, arrays and compound data types, which alongside macros provided the necessary foundation to create abstract data types

https://www.softwarepreservation.org/projects/LISP/interlisp...

And going back to CLU,

> The language which most closely resembles, in form, the language presented here is SIMULA 67. 8 SlMULA class definitions have many similarities with cluster definitions.

"Programming with Abstract Data Types (1974)"

https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.136...

chubot
Maybe, I'm not seeing it from those links

Either way, it doesn't really matter, as it's clear that C does not include any of those ideas, and the CII style isn't idiomatic

Especially when it was created, but even today!

pjmlp
Yeah it doesn't, that is why there are enough papers and books how to implement them with incomplete types, and translation units with statics as poor man's replacement for modules.
chubot
Again, there is already a well known solution for this problem -- C++

And it's trivial to upgrade to from C

So basically, use EITHER idiomatic C, which means long functions / few internal interfaces, reuse with ABIs not APIs, bespoke data structures, etc.

OR use C++ and ADTs (type safety, abstraction, polymorphism). Or use Rust if you don't need compatibility.

So books like CII are of very limited use, especially not for beginners. They will be fighting with the language and not understanding what it's about.

pjmlp
I guess those books are for the folks that will never touch anything besides C, no matter what.

Anyway, I agree with the sentiment.

chubot
typo: It's a minimal layer meant to generate machine code that will work on multiple different machines

i.e. it's about code generation, not abstraction, not type checking, etc.

tialaramex
I don't see how this observation that C++ STL containers aren't very good somehow "shows the folly of ADTs" ?

The fact these are abstract types doesn't seem relevant, if you explicitly implemented this feature set for, say, the long type and named it "chubots_long_set" it would still suck, but it's not abstract, the abstraction played no part.

chubot
I don't have any problem with ADTs or abstraction ... In fact I'd say the strength of C++, and why I use it, is precisely that you can create your own abstractions, more so than C.

I'm just saying that using a canned set with "many useful" operations is suboptimal, design by committee is suboptimal, etc.

As opposed to analyzing the ops your app needs and creating custom data structures. i.e. there are many different ADTs for "hash table" or "set"

That might seem obvious, but it's not how software development is being done today. There's a lot of code reuse that leads to suboptimal software; it would actually be better to copy and paste and refine more.

tialaramex
I still think you're mostly conflating "the C++ standard library provides bad implementations of this stuff" which is famously true, with "generic solutions are just bad" which is at least non-obvious and I'd argue generally false.

> copy and paste and refine more.

That doesn't get you better algorithms, which is what you need. If you start with the C++ standard library's unordered_set implementation in a source file and you "refine" that you won't get from there to absl::flat_hash_set except in the same sense you could start with the footage from "Grease" and end up making "Bugsy Malone". Start over with a different design.

chubot
It's not either-or, both things can be true

There are apps where absl:flat_hash_set isn't optimal either

tialaramex
Picking from a handful of options like absl::flat_hash_set rather than always hand-rolling is a clear win for productivity. As with anything else in performance, measure first and only solve problems you actually have applies to the idea that maybe the choice doesn't work - even for the abysmal std::unordered_set if you don't have measurements showing it's a problem then it probably just isn't a problem.
sfpotter
I don't take the point of this book to be "how to implement an STL-like data structures and algorithms library in C"---although you were his coworker, so maybe you know better. I've always viewed it more as "how to build data structures with useful interfaces in C". In the book, the set of libraries presented are an example which illustrates how to approach this using the features that C provides. If you are new to C and don't know how to manage complexity by building up useful interfaces for your data structures, reading Hanson's book is a reasonable way to get some ideas. Another way to go would be to just read through the source of any of the libraries you mentioned, all of which do in fact use ideas which feature in this book. This is obviously not to say that Hanson's book originated these ideas. I also think focusing on the exact style of the code in this book is maybe a bit of a red herring.
chubot
You could view it as an example not meant to be used, sure

I'd say it's still easy to get the wrong idea -- the title is "C Interfaces and Implementations: Techniques for Creating Reusable Software"

So the claim is that focusing on reuse is missing what C is good for. It's going against the grain; if you want that style, use C++ or Python

Those were less viable choices when the book was written, which is another reason I wouldn't recommend this old book, especially to beginners.

http://drh.github.io/cii/

Also the techniques for real long-term reuse involve C ABIs and not C APIs, which are not covered in almost any book, including this one.

sfpotter
I'm sorry, I don't completely understand what your point. You seem to be alluding to "what C is actually good for", but it's not clear to me what that's supposed to be. I understand that you think C should not be used to develop generic components that are reused, and that data structures and such should be re-rolled or copy-pasted each time they're used.

On the other hand, you do hint that you think C can be used reusably, provided that the ABI is the focus. I agree with this.

In my opinion, the techniques discussed in the book are in fact useful techniques for accomplishing exactly this end. If you want reusability the ABI way, what you want is a small surface area which changes extremely slowly. Ideally, you want each ABI to be a subset of the last to avoid breaking changes. OK: accomplishing data hiding via opaque pointers in tandem with a simple, high-level interface is one way to accomplish this, and is the main lesson to be learned by reading this book. (I would argue you really only need to read a chapter or two to learn it, but that's a different story---I would argue that this book is in fact not very good for this reason, but whatever.)

If you look at most reusable C libraries, they take this approach. Obvious this book takes a bit of an extreme approach where as much of the details of a data type are hidden as possible, but there is no real reason to do this provided that the details of a type are stable. Then it's OK to expose them as part of the interface.

I suppose I take your point that in reading this book, one might get the idea that it's a good idea to develop an STL-style library to use with C and run with that. On the other hand, someone who is learning C might just as well read many books about it (or read lots of code), and be able to contextualize this book well enough to understand that it should be taken with a grain of salt.

I think it's also important to point out that there are exceptions to these "rules". GLib is a generic STL-style library written in C which seems to be pretty widely used. At the other end of the spectrum, you have more people (I think mostly in the games community) developing "header only C libraries". YMMV.

chubot
This comment sums it up best:

https://news.ycombinator.com/item?id=33142349

So basically, use EITHER idiomatic C, which means long functions / few internal interfaces, reuse with ABIs not APIs, bespoke data structures, etc.

OR use C++ and ADTs (type safety, abstraction, polymorphism). Or use Rust if you don't need compatibility.

So books like CII are of very limited use, especially not for beginners. They will be fighting with the language and not understanding what it's about.

----

To sum it up, C is better for coarse-grained reuse (deep interfaces a la Ousterhout, Unix file system) than fine-grained reuse like CII (hash table, array, set)

Related long article I wrote about API (compile time) vs. ABI (protocol, runtime) and related issues: https://www.oilshell.org/blog/2022/03/backlog-arch.html

----

I'll take your point that if you want ABI stability, then hiding layout behind a pointer and not exposing structs is a good idea!

Although that pointer's type doesn't necessarily have to be void* as it is in CII -- it could just be an application-specific type

Also agree that there are several different ways of using C and C++.

sfpotter
Why is "idiomatic C" equivalent to "long functions and few internal interfaces"?

The whole point of having a small surface-area for your ABI with plenty of detail hiding is that you are free to do what you like beneath it. If the code uses a struct named "hash_map" that takes a generic hash function and stores void pointers, but runs fast for my purposes, what do I care? These techniques give you a controlled way to build black boxes.

C is a very flexible language, and it is possible to build up quite a variety of patterns in it. Your job as an engineer is to look in your toolbox and select the best tool for the job. Adhering to a "correct idiom" gets in the way of this.

belter
For the professional programmer, knowing other languages and getting into C, besides the two great recommendations above, would recommend:

"C Programming: A Modern Approach, 2nd Edition" - https://www.amazon.com/C-Programming-Modern-Approach-2nd/dp/...

Note the above book is good for its quality as a reference, but not enterily considered as "modern". For a more updated approach I would also recommend:

"Modern C" - https://www.manning.com/books/modern-c

and

"Effective C" - https://nostarch.com/Effective_C

The first book on the language:

"C Programming Language, 2nd Edition" - https://www.amazon.com/Programming-Language-2nd-Brian-Kernig...

Is interesting from a historical perspective, but considered as not a recommended resource for learning C.

Edit: If you are learning C there is something quite important you need to know... C and C++ are two completely different languages, and that is how you should approach your learning. In other words, don't go learning the C in C++ :-)

belter
Edit: If you are learning C there something quite important you need to know... C and C++ are two completely different languages, and that is how you should approach your learning. In other words, don't go learning the C in C++ :-)
rramadass
I would like to add two more to your recommendations;

1) An old classic to understand low-level C "System" interface: The C Companion by Allen Holub.

2) Followup with the more modern Computer Systems: A Programmer's Perspective by Randal Bryant and David O'Hallaron.

AlexeyBrin
I found the first book in a second hand shop a few years ago, but unfortunately it didn't came with the diskette. Any change you can upload the code from the diskette somewhere or point me to where I can find it ?
leaveyou
You are welcome.

https://github.com/drh/cii

CodeSgt
I've got to ask, in what ways does the first suggestion compare to Modern C and The C Programming Langauge? Those are the other 2 strong contenders I've been suggested
mhd
One can only learn a language one time, so I've got a hard time recommending first books. But I definitely second the recommendation for the second book here ;)

Hanson's style is a bit idiosyncratic, with his somewhat Modula-3-ish naming style and literate programming use, but there are a lot of usable data structures in there, and I especially like that the focus is on the module level, not on the algorithms themselves.

Now, having said that, if you're in a particularly weird sub-domain of C, books from there might supersede or at least color a lot of what you're doing on a day to day basis. In the days of yore, if you wanted to do Win16/Win32 programming, getting to work with your Petzold early is a good idea, and I would assume the same to be true if you do glib/gobject based Gtk programming.

Two free resources that looked good to me and that I forwarded in the past were "An Introduction to the C Programming Language and Software Design"[1] by Tim Baily and "Beej's Guide to C Programming"[2]. Those are a bit more concise than your average intro to C book, but for some paths (prior experience, quick headway to C++ etc), they might be sufficient.

[1]: https://www-personal.acfr.usyd.edu.au/tbailey/ctext/ctext.pd...

[2]: https://beej.us/guide/bgc/

tdrgabi
Would David Hanson's book be useful for non C programming?

Will it help me understand how to build reusable, language agnostic, code?

rramadass
Yes, Absolutely.

However, i am not clear what you mean by "language agnostic"? Obviously Code cannot be language independent but if you can read C then you should be able to translate the data structures/algorithms given in this book to a language of your choice; the difficulty might vary (eg. how would you represent pointers in your language to implement say recursive tree structures?) but it can be done. The data structures/algorithms given in Hanson's book are "industrial strength" with no missing parts (i.e. no exercise left to the reader). So you get complete code all written in the "Literate Programming" style which takes a little getting used to but is eminently worth it.

jart
It is possible to write language agnostic code. Consider SectorLISP which is written in C that's also valid JavaScript See https://justine.lol/sectorlisp2/#evaluation and https://github.com/jart/sectorlisp/blob/c9ce1c54a024ac4774a2... and also https://github.com/jart/sectorlisp/blob/main/lisp.c
rramadass
Pretty Neat! I had come across similar techniques in Arthur Whitney's work (past HN threads).

However i interpreted the original "language agnostic" question as maybe wanting to implement the C code in terms of some pseudo-code and hence my question. The phrase also seems to have another meaning: https://en.wikipedia.org/wiki/Language-agnostic

chubot
I wouldn't recommend it for that (see sibling comment). Reuse isn't as idiomatic in C as it is in other languages, for reasons inherent in the language, e.g. see all widely used C codebases
mhd
I think it's a lot less useful for that. The problem is that doing that with C is that you're already strapping some lead to your feet from the very start, so a lot of what CII does is removing those weights by adding stuff from other languages, either by merit of coding style or new libraries. This would already go to far for a lot of C purists, but it doesn't totally try to work deny the language you're working in.

So it does basic error handling & modularization. You get that "for free" in a lot of other languages, or sent in totally different directions anyway (good modularization in OO and/or FP looks somewhat different)

Then there's a lot of practical data structures and algorithms, with good references to other versions and sources, so both something you could use immediately but also serving as jumping off points to advanced study.

So I appreciate it a lot more in combination with bare bones C than with other languages or even C environments with more standard library functions.

For style & technical guidelines, I think Code Complete is still a great book, or the Pragmatic Programmer. For a trad-C book, maybe even Pike's Practice of Programming. Avoid anything avuncular.

Of recent years (and not including OO stuff in general), Ousterhout's "A Philosophy of Software Design" packs a lot in a few pages.

Please check "The C Interfaces and Implementations" book by David Hanson [1]. Someone has implemented the concept using his library that you can check and use [2].

Another excellent reference is the "The Linux Programming Interface" book by Michael Kerrisk that documents most of the API available under Linux [3].

[1]https://www.amazon.com/dp/0201498413

[2]https://github.com/gon1332/gonlibs

[3]https://www.amazon.com/Linux-Programming-Interface-System-Ha...

Hanson's C Interfaces and Implementations [0] is one of the best books on the subject.

Strongly complemented by Sedgewick's Algorithms in C.

[0] https://www.amazon.com/Interfaces-Implementations-Techniques...

zengid
I added both to my wish-list; Thanks!
This book (C Interfaces and Implementations: Techniques for Creating Reusable Software) has a whole section on it:

https://www.amazon.com/Interfaces-Implementations-Techniques...

I'd recommend Ben Klemens' excellent book "21st Century C - Tips from the New School" [0]. This book teaches you modern C techniques and, most importantly, the tooling that modern C programmers use (git, autotools, valgrind, etc.) It also covers commonly used libraries to help you from reinventing the wheel (GLib, POSIX standard, SQLite, libxml, & cURL.)

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

[3] http://blog.regehr.org/

[4] http://blog.regehr.org/archives/1393

May 12, 2016 · sn9 on Teaching C
Much of the code in the fantastic C Interfaces and Implementations [0] is inspired by Modula-3. It's a fantastic book to work through after finishing K&R for anyone wanting to learn how to write safe and reusable C code.

(Regular HN readers will recognize the author of the top review on Amazon.)

[0] http://www.amazon.com/Interfaces-Implementations-Techniques-...

nickpsecurity
Wow. Interesting to see the two converge that way. That's the glowing review I've seen of a book in a while. Guess I'm going to have to get it just in case. :)
I suggest C Interfaces and Implementations: Techniques for Creating Reusable Software by David Hanson.[1] It focuses on helpful engineering practices for reliably and efficiently implementing algorithms in C.

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-...

"With OOP it's all about classes, abstractions, interfaces etc. and design patterns."

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.

[1] http://www.amazon.com/dp/0201498413

ectoplasm
You don't need function pointers without inheritance, just take an instance pointer as the first parameter to each class member function.
K&R is more of a reference, I'd suggest this instead:

"C Interfaces and Implementations" by David R. Hanson http://www.amazon.com/Interfaces-Implementations-Techniques-...

I like to recommend C Interfaces & Implementations

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...

two things come to mind.

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.

Nov 01, 2012 · meta on Show HN: Introducting C+
Cool idea.

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?

MetallicCloud
I'm just guessing here, but I assume the variables are created on the stack, then copied into the table object, rather than references being passed to the table. So when the function would end, the original variables would be destroyed, but the copies would remain.
orangeduck
This is correct. "Table" is a datatype which copies the values into the table, while "Dict" is a data type that holds references to the objects. The same semantics hold for "Array" and "List".

Although not perfect this was probably the best way I could have designed such structures. There is some info in the header files as to how to use them.

Jun 14, 2012 · nvoorhies on C vs GO
C Interfaces and Implementations: Techniques for Creating Reusable Software is the best thing I've seen on the topic, personally. http://www.amazon.com/Interfaces-Implementations-Techniques-...
If you like this article, the book C Interfaces and Implementations[1], goes into this exact technique in great detail, along with many other useful ones.

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.

[1] http://www.amazon.com/gp/product/0201498413/

There's also a much cleaner way to have interfaces and implementations in C, without relying on macro hackery.

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.

scalyweb
This is one of the last books that I'm still hoping will make it to a digital format somehow. I just can't see ordering a new paper copy again.
tptacek
This is my favorite C book ever, I recommend it wholeheartedly, and it recommends voidstars. =)
nkurz
Respectful of you but not of the book, I have to ask: what do you like about it? My initial reactions were very negative (http://news.ycombinator.com/item?id=1705332). I love K&R, but recoiled in horror at every page I managed to read of this book.

I've written entire macro-based systems similar to those recommended by the author here, and find them very useful. Void pointers are great where they can be used, but I love the efficiency and clarity of the generated code approach.

tptacek
I found your objections to this book pedantic.

For instance, in a chapter on string atoms (symbols) --- a concept which virtually no C program in the world takes advantage of, despite the centrality of the concept to Lisp, Python, and Ruby --- and this is the first chapter in the book --- you were shocked by his use of a 43 byte string to hold a number string... because someone might be using that code on a 192 bit machine?

You missed the forest for the trees. If you don't want your code tainted by the number 43, don't write that code. The point of the book is how you structure your code, divide it into subsystems, and present coherent interfaces to the rest of your program.

nkurz
I'm not bothered by the idea of a fixed length for strings, rather the explanation that it is best to use the number 43 instead of a named constant (MAX_STRING_LEN) to avoid namespace pollution. If the first paragraph I quoted had been standalone, or better as a short comment, I would have been in full approval.

Anyway, I appreciate your response. It's good try to appreciate what others see that I do not. Yes, if you ignore the details of the code and the explanations, there are some good parts. If you look _only_ at the big picture, it's probably a fine book. And I love his clearly prefixed naming conventions. But I think you'd do a lot better reading something like the SQLite source code rather than this book if you want to see examples of good C.

I guess I have to ask: do you feel that chapter 4 on using setjmp() and longjmp() plus some brittle macros for error handling is also good for learners? I thought it was technically very clear but about 40 years out of date as to good practice. Is this a forest or a tree?

loewenskind
As I recall, Meyer also recommends voidstars for generic collection implementations to deal with template bloat.
strlen
To those who don't yet have it on their shelves, source is available here:

http://code.google.com/p/cii/source/browse/#svn/trunk

I may be using the word 'modern' a bit liberally here, but these are all more recent than K&R at least. 'C A Reference Manual' I think is what a lot of people really want out of a C book and 'Expert C'/'C Traps and Pitfalls' both help with all of the less intuitive parts of the language that you don't really get out of K&R.

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...

C Interfaces and Implementations is really good: http://www.amazon.com/Interfaces-Implementations-Techniques-...
nkurz
Different books work for different folks, and lots of people seem to love this one. I however love C and found this book to be an abomination. K&R is brilliant. Given an opportunity, I would eradicate this book from the face of the earth lamenting only the damage it has already done.

Examples provided here: http://news.ycombinator.com/item?id=1705332

I would recommend David R. Hanson's book C Interfaces and Implementations. It is an extremely well documented library and shows you how to design APIs properly.

http://www.amazon.com/Interfaces-Implementations-Techniques-...

mhd
I'd second that. Beyond just getting a good code base, it's quite likely that you get some good ideas for APIs and algorithms.

Beyond that, Tcl/Tk is a large-ish codebase that's still quite manageable, especially considering its age and the many rewrites.

For a more idisyncratic view, I once went through Rob Pike's sam editor. No header guards, sparse comments, short variable and function names. But you could still figure out what's going on without any problems. That was the old portable sam, don't know if the current plan9port one is still that good.

nkurz
Based on the recommendations here, I just got this book by interlibrary loan. I haven't read much of it yet, but I'm glad I didn't buy it sight unseen. It's an understatement to say does not meet the expectations I had for it. Perhaps one could develop a good course around it, and I'm sure there are good things an experienced coder could gleam from it, but as a standalone text for a beginner I think it would do more damage than good.

I thought at first that the code samples he was giving were examples of "what not to do", and then was astonished to find him defending them in the text. From page 36, after some horrendous code for Atom_int() page 35:

"When the conversion is done, s points to the desired string, and this string has &str[43] - s characters. str has 43 characters, which is enough to hold the decimal representation of any integer on any conceivable machine. Suppose, for instance, that longs are 128 bits. The string representation of any 128-bit signed integer in octal - base 8 - fits in 128/3 + 1 = 43 characters. The decimal representation can take no more digits than the octal representation, so 43 characters are enough.

The 43 in the definition of str is an example of a 'magic number,' and it's usually better style to define a symbolic name for such values to ensure that the same value is used everywhere. Here, however, the value appears only once, and sizeof is used whenever the value is used. Defining a symbolic name might make the code easier to read, but it will also make the code longer and clutter the name space. In this book, a symbolic name is defined only when the value appears more than once, or when it is part of an interface."

I'm glad to see his priorities presented in such a clear manner. If you feel that your current code is too readable at the expense of "name space clutter", this might be a good book for you. But otherwise, just say no!

ps. In case this example didn't convince you, the following chapter on using setjmp() and longjmp() to roll your own macros for exception handling might be worth glancing at in the online version before you confirm your purchase.

HN Books is an independent project and is not operated by Y Combinator or Amazon.com.
~ yaj@
;laksdfhjdhksalkfj more things
yahnd.com ~ Privacy Policy ~
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.