flexible array member in a nested struct

孤街浪徒 提交于 2019-11-29 14:32:37

It's not valid per the standard. I'm not sure how reliable it is in practice.

C11 (ISO/IEC 9899:2011), §6.7.2.1.3 says the following (emphasis mine):

A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.

Later on, §6.7.2.1.18 clarifies that the above is referring to flexible array members (FAMs):

As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.

From some quick experimentation, GCC and Clang both add the trailing padding required to align the FAM properly even when the struct is nested, and only warn about structures with FAMs being members of other structures or arrays if -Wpedantic is passed, so take that as a sign that it'll probably work if you will :). It feels a bit hackish though.

Note that it probably wouldn't make sense to have the FAM anywhere but at the end. If you do

struct e {
    struct d d;
    int n;
} e;

, then e.d.ns[0] and e.n are likely to overlap in memory.

Try something like this;

struct d {
    char c;
    int ns[];
};

struct a {
    int n;
    int d_fam[];
};

int main() {
    const int n = 10;
    struct a *pa = malloc(offsetof (struct a, d_fam) + offsetof (stuct d, ns) + n * sizeof(int));
    struct d *pd = pa + (uintptr_t) offsetof (struct a, d_fam);
    pa->n = n;
    pd->c = 1;
    for (int i = 0; i < n; ++i) {
        pd->ns[i] = i;
    }
    for (int i = 0; i < n; ++i) {
        printf ("%d\n", pd->ns[i] + pd->c);
    }
    free(pa);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!