Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Is it valid C code to have flexible array members inside nested structs? So is my sample code below guarenteed to work as expected with a sane compiler?

#include <stdio.h>
#include <stdlib.h>

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

struct c {
    struct d d;
};

struct b {
    struct c c;
};

struct a {
    int n;
    struct b b;
};

int main() {
    const int n = 10;
    struct a *pa = malloc(sizeof(*pa) + n * sizeof(pa->b.c.d.ns[0]));
    pa->n = n;
    pa->b.c.d.c = 1;
    for (int i = 0; i < n; ++i) {
        pa->b.c.d.ns[i] = i;
    }
    for (int i = 0; i < n; ++i) {
        printf("%d
", pa->b.c.d.ns[i] + pa->b.c.d.c);
    }
    free(pa);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
957 views
Welcome To Ask or Share your Answers For Others

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...