Доброго дня.
Меня интересует, как можно разместить opaque type на стеке, использовав его нативное выравнивание. Пока у меня есть такое:
/* foo.h */
#ifndef FOO_H
#define FOO_H
#include <stddef.h>
#include <stdalign.h>
typedef struct foo Foo;
typedef unsigned char foo_store;
extern const size_t foo_sz;
extern const size_t foo_align;
Foo* foo_init (void);
Foo* foo_init_local (foo_store *store);
#define foo_local(x) alignas(max_align_t) foo_store x[foo_sz]
#endif //FOO_H
/* foo.c */
#include <stdlib.h>
#include "foo.h"
struct foo {
int a;
float b;
double c;
void *ptr;
};
const size_t foo_sz = sizeof(struct foo);
const size_t foo_align = alignof(struct foo);
inline static void assign (struct foo *f);
struct foo* foo_init (void) {
Foo *f = malloc(sizeof *f);
assign(f);
return f;
};
struct foo* foo_init_local (foo_store *store) {
struct foo *f;
if (!store)
return NULL;
f = (struct foo*)store;
assign(f);
return f;
};
inline static void assign (struct foo *f) {
f->a = 1;
f->b = 2.0;
f->c = 3.0;
f->ptr = (void*)0xB16B00B5;
}
/* main.c */
#include <stdalign.h>
#include "foo.h"
int main (void) {
foo_local(store);
Foo *f = foo_init_local(store);
return 0;
}
Всё вроде как работает нормально, но используется выравнивание по границе 16, а не 8. Условие: нельзя тупо задефайнить FOO_ALIGN 8 в foo.h (ну типа вдруг я захочу изменить состав struct foo). Я почему спрашиваю-то вообще. Вот говорят, что плохо выделять маленькие структуры в куче из-за её фрагментации (вопрос производительности не рассматриваем). Не возникнет ли некоего подобия фрагментации на стеке из-за несоответствующего выравнивания? Ведь адресов, кратных 16 в два раза меньше, чем кратных 8 (да ведь?). Ну и заодно: как malloc() выравнивет память? Надеюсь, понятно объяснил. Мне это ни для чего не надо, спрашиваю из интереса.