Yes, the general idea of the hack is valid, but at least as I read it, you haven't implemented it quite correctly. This much you've done right:
f = malloc(num + sizeof(foo) + MAX_COMMENT_SIZE );
f->data = f + 1; // is this OK?
But this is wrong:
f->comment = f + 1 + num;
Since f is foo *, the f+1+num is computed in terms of sizeof(foo) -- i.e., it's equivalent to saying f[1+num] -- it (attempts to) index to the 1+numth foo in an array. I'm pretty sure that's not what you want. When you allocate the data, you're passing sizeof(foo)+num+MAX_COMMENT_SIZE, so what you're allocating space for is num chars, and what you (presumably) want is to point f->comment to a spot in memory that's num chars after f->data, which would be more like this:
f->comment = (char *)f + sizeof(foo) + num;
Casting f to a char * forces the math to be done in terms of chars instead of foos.
OTOH, since you're always allocating MAX_COMMENT_SIZE for comment, I'd probably simplify things (quite) a bit, and use something like this:
typedef struct foo {
char comment[MAX_COMMENT_SIZE];
size_t num_foo;
char data[1];
}foo;
And then allocate it like:
foo *f = malloc(sizeof(foo) + num-1);
f->num_foo = num;
and it'll work without any pointer manipulation at all. If you have a C99 compiler, you can modify this slightly:
typedef struct foo {
char comment[MAX_COMMENT_SIZE];
size_t num_foo;
char data[];
}foo;
and allocate:
foo *f = malloc(sizeof(foo) + num);
f->num_foo = num;
This has the additional advantage that the standard actually blesses it, though in this case the advantage is pretty minor (I believe the version with data[1] will work with every C89/90 compiler in existence).