【问题标题】:Is empty array in the end of the structure a C standard?结构末尾的空数组是 C 标准吗?
【发布时间】:2014-03-06 09:32:10
【问题描述】:

我注意到开源项目中经常使用结构体末尾的空数组:

typedef struct A
{
    ......
    void *arr[];
} A;  

我想知道这是 C 标准吗?还是只适用于 gcc 编译器?

【问题讨论】:

    标签: c


    【解决方案1】:

    从 C99 开始,它现在是 C 标准。 C99 之前的编译器可能不支持它。旧方法是声明一个 1 元素数组,并为此调整分配大小。

    新方法:

    typedef struct A
    {
        ......
        void *arr[];
    } A;  
    
    int slots = 3;
    A* myA = malloc(sizeof(A) + slots*sizeof(void*));
    myA->arr[2] = foo;
    

    老办法:

    typedef struct A
    {
        ......
        void *arr[1];
    } A;  
    
    int slots = 3;
    A* myA = malloc(sizeof(A) + (slots-1)*sizeof(void*));
    myA->arr[2] = foo;
    

    【讨论】:

    • 以下情况可能吗?那是为了数据对齐,结构A的末尾有填充字节。所以myA->arr[0]和myA->arr[1]之间有一个间隙。
    • 填充会导致分配比实际需要更多的内存,但不会导致数组槽地址的计算出现问题。如果sizeof(void*)==4,那么arr[1]将在arr[0]之后的四个字节,无论A如何填充。
    • 不错,不过。你是对的,填充使这种技术有点奇怪。
    【解决方案2】:

    6.7.2.1 的标准(草案 N1570)18 规定:

    作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能 数组类型不完整;这称为灵活数组成员。在大多数情况下, 灵活的数组成员被忽略。特别是,结构的大小就像 灵活的数组成员被省略,除了它可能有更多的尾随填充比 遗漏将意味着。然而,当一个 . (或 ->)运算符有一个左操作数,即 (指向)具有灵活数组成员和正确操作数名称的结构 成员,它的行为就好像该成员被替换为最长的数组(具有相同的 元素类型)不会使结构大于被访问的对象;这 数组的偏移量应保持灵活数组成员的偏移量,即使这会有所不同 从替换阵列的那个。如果这个数组没有元素,它的行为就像 它有一个元素,但如果尝试访问该元素,则行为未定义 元素或生成一个越过它的指针。

    【讨论】:

    • 引用标准很好,但解释为什么有人会这样做以及如何在实践中使用它会很好。
    猜你喜欢
    • 2020-06-14
    • 2014-12-30
    • 1970-01-01
    • 2014-09-03
    • 2012-03-27
    • 1970-01-01
    • 2016-09-06
    • 2013-06-22
    • 2010-12-21
    相关资源
    最近更新 更多