简体   繁体   English

嵌套结构中的灵活数组成员

[英]flexible array member in a nested struct

Is it valid C code to have flexible array members inside nested structs? 在嵌套结构中有灵活的数组成员是有效的C代码吗? 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\n", pa->b.c.d.ns[i] + pa->b.c.d.c);
    }
    free(pa);
}

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): C11(ISO / IEC 9899:2011),§6.7.2.1.3说明以下(强调我的):

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): 后来,§6.7.2.1.18阐明了上述内容是指灵活的阵列成员(FAM):

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 :). 从一些快速实验中,GCC和Clang都添加了正确对齐FAM所需的尾随填充,即使struct嵌套时也是如此,并且只有在传递了-Wpedantic时才警告FAM是其他结构或数组的成员的结构,所以请将其作为如果你愿意,它可能会起作用的迹象:)。 It feels a bit hackish though. 虽然感觉有点hackish。

Note that it probably wouldn't make sense to have the FAM anywhere but at the end. 请注意,将FAM放在任何地方但最后都没有意义。 If you do 如果你这样做

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

, then edns[0] and en are likely to overlap in memory. ,然后edns[0]en可能在内存中重叠。

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM