clever c trick
Mar 14, 2009I had a few days of vacation visting my folks and started a little hobby hacking in the evenings- the details of which are grist for other, longer posts- but the set up is that I’m working on an FFI (foreign function interface) and have a variety of structs that I want to pass back and forth. I don’t want to handle each struct with unique getter/setters or use hairy if/else or switch/case statements because it’s tedious to write and hard to maintain and I’m not sure where I’m going with this code. I worked out a generic dispatch function with a jump table and having the C preprocessor and compiler build most of it for me. To do that I needed to get the offset of the structure member and its size and came up with this preprocessor macro:
@
#define _off_sz(type,memb) offsetof(type,memb), sizeof(((type
*)0)->memb)
@
I’d never seen it before and thought myself quite clever with the cast
zero since I can do this:
#include <stddef.h>
#include <stdlib.h>
...
typedef struct tag_vtable_rec {
pointer (*fp)();
int argc;
size_t offset;
size_t size;
} vtable;
...
vtable ffi_foo_vt[] = {
{ some_func, 2, _off_sz(SomeStruct, SomeMember) },
{ other_func, 1, _off_sz(SomeStruct, OtherMember) },
...
};
...
It turns out that this technique of casting zero and using `sizeof()` is old and well-known. I have found it argued over in `comp.lang.c` at least as early as 2002 and Nigel Jones wrote a macro almost exactly like mine (and properly casts the `sizeof()` result to `size_t`, which I’ll fix) in 2004 for Embedded Systems Magazine.