So, yeah, this, as presented in the article, is a bad idea.
char buf[BIG_ENOUG_SIZE];
struct something *foo;
struct something_else *bar;
// point foo to the beginning of buf
foo = (struct something *) buf;
// point bar to the location after foo inside buf
bar = (struct something_else *) (buf + sizeof(struct something));
You can’t be certain that everything is going to align properly here, namely on the border between the struct something and struct something_else.
The article advocates for this because otherwise you use twice the memory. Is that extra memory on the stack? In that case, it may not matter. If you don’t have a stack (and lots of 8-bit microcontrollers don’t), then do yourself a favour and do this instead:
And honestly, there doesn’t seem to be a good reason why they have to be adjacent in memory in the first place. [edit: the article does offhandedly mention that “it needs them concatenated into a single buffer”. Sounds dubious, but it’s not explained, so I’ll let it slide.] So just declare them as static globals and don’t worry about it.
Or would that also have the same alignment issues? I was under the impression that Microsoft Windows API uses this trick (well the older way pre-dating C99) in some APIs as mentioned on Old New Thing.
I think that one might be okay, since cls_extra is now aligned as a pointer, but there might still be some weird layout that would cause a problem.
Bear in mind the article is writing in the context of 8-bit microcontrollers, so there are two things to consider: the size of things tends to be not what you think (and thus alignment can be bizarre), and use of malloc is practically forbidden. (If you don’t have a stack, you probably don’t have a heap, either.)
So, yeah, this, as presented in the article, is a bad idea.
You can’t be certain that everything is going to align properly here, namely on the border between the
struct somethingandstruct something_else.The article advocates for this because otherwise you use twice the memory. Is that extra memory on the stack? In that case, it may not matter. If you don’t have a stack (and lots of 8-bit microcontrollers don’t), then do yourself a favour and do this instead:
And honestly, there doesn’t seem to be a good reason why they have to be adjacent in memory in the first place. [edit: the article does offhandedly mention that “it needs them concatenated into a single buffer”. Sounds dubious, but it’s not explained, so I’ll let it slide.] So just declare them as static globals and don’t worry about it.
Another option I would think is to use a flexible array member inside struct something like this:
Then when allocating later in your code:
Or would that also have the same alignment issues? I was under the impression that Microsoft Windows API uses this trick (well the older way pre-dating C99) in some APIs as mentioned on Old New Thing.
I think that one might be okay, since
cls_extrais now aligned as a pointer, but there might still be some weird layout that would cause a problem.Bear in mind the article is writing in the context of 8-bit microcontrollers, so there are two things to consider: the size of things tends to be not what you think (and thus alignment can be bizarre), and use of
mallocis practically forbidden. (If you don’t have a stack, you probably don’t have a heap, either.)