是否允许返回具有灵活数组成员的结构?

时间:2019-10-14 05:22:18

标签: c arrays language-lawyer flexible-array-member

GCC编译函数返回带有灵活数组成员fine的结构。该标准在6.7.2.1中给出了如何处理此类结构的定义:

  

在大多数情况下,柔性数组成员将被忽略。在   特别是结构的大小就像是柔性数组   成员被省略,除了它的尾随填充可能比   遗漏意味着。

由于已知具有灵活数组成员的结构的大小,因此根据6.2.5中给出的完整性定义,类型是完整的:

  

在翻译单元内的各个点上,对象类型可能是   不完整(缺少足够的信息来确定   该类型的对象)或完整的(具有足够的信息)。 37)

也是6.5.2.2

  

表示被调用函数96)的表达式应具有类型   指向返回void或返回完整对象类型的函数的指针   除了数组类型。

因此,返回具有灵活数组成员的struct是合法的。


如何修复下面的示例以使其正常运行(我需要使用弹性数组成员为堆栈分配结构):

#include <stdio.h>

struct test{
    size_t sz;
    char data[];
};

struct test get_test(void){
    int sz = 5;
    char data[5] = "test";
    struct test test = {.sz = 5};
    //How to copy char data[5] into the struct test test?
    return test;
}

int main(void){
    struct test tst = get_test();
    printf("%s\n", tst.data);
}

2 个答案:

答案 0 :(得分:4)

  

如何修复下面的示例以使其正常运行(我需要堆叠   具有灵活数组成员的已分配结构):

灵活数组成员允许对结构和FAM进行单个动态分配。 (您不能为堆栈分配结构和动态FAM,如果要这样做,请不要使用FAM,而应使用data的指针。)要分配和利用FAM,您需要更改函数以返回指向类型struct test的指针(例如struct test*),然后在结构"test"中声明并分配用于结构的存储和用于get_test的存储,并返回指向已分配块的指针,例如

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

struct test {
    size_t sz;
    char data[];
};

struct test *get_test (void)    /* declare as type struct test* */
{
    size_t sz = 5;
    char data[] = "test";

    /* allocate storage for struct + FAM */
    struct test *test = malloc (sizeof *test + sizeof data);
    if (!test)
        return NULL;

    test->sz = sz;                              /* assign sz */
    memcpy (test->data, data, sizeof data);     /* copy data */

    return test;
}

int main (void) {

    struct test *tst = get_test();

    printf ("test->sz   : %zu\ntest->data : %s\n", tst->sz, tst->data);

    free (tst);     /* don't forget to free what you allocate */
}

使用/输出示例

$ ./bin/fam
test->sz   : 5
test->data : test

答案 1 :(得分:3)

是的,返回这样的值是有效的C,但是不会复制任何数组元素。自动变量的行为就好像它确实分配了一个长度为1的数组(因为数组长度为0在标准C中无效),但是对.data[0]的访问将具有UB-实际的 size 可能包含.data[0]甚至可能包含更多连续元素-否则不包含(C11 6.7.2.1p18)。

不可能在标准C 中定义一个在可变数组成员中具有任何内容的自动变量(扩展可能存在并且确实存在)!

赋值也是有效的(因此也返回),但是柔性数组成员在赋值后仍将包含不确定值(C11 6.7.2.1p25)。