struct foo {
int a[N];
int b;
};
If not, is the following sufficient in all cases?
#define endof(o) ((char *)(&(o)) + sizeof(o))
If that is really what you want, then it's correct
What do you intend to use it for?
I'll give you two examples.
1) I have a habit of using limit pointers where someone might normally
pass a size. For example instead of using strncpy I prefer the following
function instead:
int
str_copy(const unsigned char *src,
const unsigned char *slim,
unsigned char *dst,
unsigned char *dlim,
int n);
The idea is that it's a little less error prone to assert 'src < slim'
as opposed to 'n > 0' and then also have to adjust n by some appropriate
amount. Now if all of your string processing functions are designed
like this, they tend to cascade together resulting in overall smaller
code. This is safer because slim never changes.
So sometimes I find myself computing where the end of an object is. For
example:
struct foo {
int i;
char name[NAME_MAX];
};
str_copy(src, slim, f->name, endof(f->name));
This case is a little too simple to illustrate its usefulness but I do
a lot of complex decoding and encoding of formats and find techniques
like this important.
2) Another case is when I embed a bitset at the end of a struct to allow
the number of bits to be variable like:
struct fancy_array {
...
void *blim; /* endof bitset */
char bitset[1]; /* incomplete */
}
struct foo {
struct fancy_array bar;
char bar_bitset[MAX_BARS / 8];
...
So bar_bitset just reserves space for the fancy_array's bitset. But to
initialize this I need to pass the end of bar_bitset so we can set blim:
fancy_array_init(&f->bar, endof(f->bar_bitset));
Mike