I'd like to ask about your opinion for a code I've figured out.
Context
I'm implementing a queue as a ring buffer. Each queue member is a struct below:
struct member {
int size;
char data[]
};
What's important in my case: for each member, the same amount of data should be allocated.
Why don't just provide array size if it's the same for every element?
I want to use multiple queues with different parameters, and just provide number of elements and max size of element buffer as arguments.
Why don't just have pointer in each entry and malloc individually?
I'd like to improve performance and store everything in one memory block, rather than multiple blocks at multiple addresses
My solution
I've got and idea how to make it work, based on 1 assumption: Member data size must be a multiple of 4 - to avoid any padding that could mess up address calculation
NOTE Macros are set just for example. I don't know the real sizes at the compile time
#define DATA_SIZE 64
#define N_OF_STRUCTS 3
struct entry {
int size;
char data[]; // 64
};
struct entry *get_at_index(struct entry *buff, int index) {
return buff +
index * (offsetof(struct entry, data) + DATA_SIZE * sizeof(char));
}
int main() {
struct entry *s0 =
malloc((sizeof(int) + sizeof(char) * DATA_SIZE) * N_OF_STRUCTS);
struct entry *s1 = get_at_index(s0, 1);
struct entry *s2 = get_at_index(s0, 2);
(s0 + sizeof(int) + DATA_SIZE)->data[0] = 'a';
(s0 + 2 * (sizeof(int) + DATA_SIZE))->data[0] = 'b';
assert(s1->data[0] == 'a');
assert(s2->data[0] == 'b');
printf("%s\n", s1->data);
printf("%s\n", s2->data);
return 0;
}
What I'd like to know
I'd like to ask what's your opinion on that.
- Is there something I didn't consider?
- Would it work on other architectures?
- Is this anti-pattern and if so, why?