Comparing the Cost of Different Multiple-return Techniques in C
spin.atomicobject.com
spin.atomicobject.com
And now you've reinvented (the basic premise of) OOP!
http://en.wikipedia.org/wiki/Object-oriented_programming#Fun...
Let's stay on topic, talking about C. We'll avoid philosophy and hype and will keep talking about the work being done in C.
Back to the main topic, using structures properly will result in the best code you can produce for anything not trivially small. Practically every CPU I know of is specifically optimized to make addressing elements in the C structure as efficient as possible.
In your case, if there are a lot of functions to which you pass the pointer to the structure, then if you take care of the organization it means that they really do have to operate on the structure. But if you have a lot of arguments to any function, you probably need some even bigger structure and pass that around.
/* okay */
struct monster {
unsigned id;
int x, y, hp;
/* etc. */
};
/* better */
struct point { int x, y; };
struct monster {
unsigned id;
struct point pos;
int hp;
};
This also allows a form of inheritance. For example if you have struct bad_monster {
struct monster base;
int badness; /* your imagination is the limit. */
};
/* this is safe */
struct bad_monster bad;
struct monster *some_monster = (struct monster *)&bad; /* equivalently &bad.base */
some_function_expecting_a_monster(some_monster);
/* only safe if it was originally a struct bad_monster */
struct bad_monster *bad_ptr = (struct bad_monster *)some_monster;
Those are the ways I tend to break up structs when writing C code. Basically by using lots of composition.This article is by clueful professionals. That book is everything except that.
Is the entire book great? No, to be honest it touched too little on the C side for me, and yeah the punk analogies was a bit annoying at times, but it did get me to look critically at how I wrote c. Much like this blog I'm writing for clarity first and not optimization.
What would you recommend for a c programming book instead of this book?
I haven't yet found a decent C book. I've found many good C++ books and have backported the lessons I've learned there into C, however.
That said I did learn a few tricks, and generally appreciated the books overall tone of you don't need to do crazy pointer stuff/malloc/realloc in C in general. If that makes any sense, have you read the Embedded TDD in C book by Pragmatic Programmers? http://pragprog.com/book/jgade/test-driven-development-for-e...
What C++ books would you recommend specifically? I find most to not really be of much help in straight C given the differences of the two languages (basically huge reliance on the standard library etc..).
The former is ostensibly about designing reusable modules for data structures (e.g. ring buffers), but also contains a lot of wisdom about API design, particularly how to make the most of what little API design tools C gives you. The latter is all over the place, from funny anecdotes about compiler bugs and programming contests to all kinds of useful C information that is too advanced for an intro book on C-the-language, but way too practical for most books on a specific domain: valuable details about linkers, symbol visibility, different kinds of allocation, and the memory hierarchy. Also, it's called "Deep C Secrets" and has a giant fish on the cover. What more do you need to know?
I skimmed "21st Century C" briefly a couple months back and didn't have strong feelings about it one way or the other.
Is there a reason the x86/64 ABIs don't specify such a way? Also, it seems that the 128-bit and larger registers aren't used as often to pass values. For something like a GUID, wouldn't they be a perfect fit? Or does the processor optimize stack handling so that it's almost as cheap as registers?
The platform ABIs mostly are the way they are for backwards compatibility at this point. They aren't particularly efficient and have weird corner cases (e.g. complex numbers are treated differently than the equivalent struct, IIRC). On x86-64 the situation is a little better, but still not ideal.
I think x86 lets you return in eax and edx, but only if you're returning a single 64-bit value, not a struct with 2 32-bits. Not 100% on all of this.
Depends entirely on the platform ABI. Under the OS X calling conventions 2x32b is returned in eax:edx (even if the 32b values are floats, which is annoying).
The graphs also show more overhead for returning a struct with additional padding. OpenBSD's memory allocator favors security rather than speed, and the extra size may have costs for buffer overruns felt elsewhere. I like testing C code on OpenBSD -- it's almost as good as valgrind for detecting memory bugs, but with significantly less overhead, since the memory checking is integrated into the OS.
One possibility is that OpenBSD uses the alternative ABI for returning structs mentioned in that post.
I've been dealing with rewrites of a few internal utilities in C (was going to use go, but the runtime has issues) and was going to start testing how struct passing with errors in a struct for example would look in C.
I'll keep an eye out thanks!