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

Is returning a struct with flexible array member allowed?

GCC 编译函数 returning 具有灵活数组成员的结构很好。该标准在 6.7.2.1:

给出了如何处理此类结构的定义

In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply.

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

At various points within a translation unit an object type may be incomplete (lacking sufficient information to determine the size of objects of that type) or complete (having sufficient information). 37)

此外,6.5.2.2

The expression that denotes the called function 96) shall have type pointer to function returning void or returning a complete object type other than an array type.

所以 return 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);
}

是C到return这样的值是有效的,但是none的数组元素会被复制。自动变量的行为就好像它分配了一个长度为 1 的数组(因为 0 的数组长度在标准 C 中是无效的),但是访问 .data[0] 将有 UB - 实际的 大小对象的 可能包含 .data[0] 甚至更多连续元素 - 或者不包含。(C11 6.7.2.1p18).

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

赋值也是有效的(因此 returning 也是有效的),但是灵活的数组成员在赋值后将再次包含不确定的值 (C11 6.7.2.1p25)。

How to fix an example below to make it work properly (I need stack allocated struct with flexible array member):

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

#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 */
}

例子Use/Output

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