Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

c - flexible array member in a nested struct

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

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

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...