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);
}
答案 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 该对象的em>可能包含.data[0]
甚至可能包含更多连续元素-否则不包含(C11 6.7.2.1p18)。
不可能在标准C 中定义一个在可变数组成员中具有任何内容的自动变量(扩展可能存在并且确实存在)!
赋值也是有效的(因此也返回),但是柔性数组成员在赋值后仍将包含不确定值(C11 6.7.2.1p25)。