One alternative to adding types is to allow enforcing consistency in some structs with the trailing array:
struct my_obj {
const size_t n;
//other variables
char text[n];
};
where for simplicity you might only allow the first member to act as a length (and it must of course be constant). The point is that then the initializer: struct my_obj b = {.n = 5};
should produce an object of the right size. For heap allocation you could use something like: void * vmalloc(size_t base, size_t var, size_t cnt) {
void *ret = malloc(base + var * cnt);
if (!ret) return ret;
* (size_t *) ret = cnt;
return ret;
}