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

St.*_*rio 2 c arrays language-lawyer flexible-array-member

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

在大多数情况下,灵活数组成员会被忽略。特别是,该结构的大小就像省略了柔性阵列成员一样,只是它可能具有比省略所暗示的更多的尾部填充。

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

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

另外,6.5.2.2

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

因此返回具有灵活数组成员的 s 应该是合法的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);
}
Run Code Online (Sandbox Code Playgroud)

Ant*_*ala 5

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

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

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