2

我需要从 C 函数返回具有灵活数组成员的结构,但不知道为什么它不能编译。我知道返回数组可以通过将它们封装在结构中来实现,如下所示:

struct data_array {
    long length;
    double data[];
};

我的功能如下所示:

struct data_array test (int length) {
    struct data_array a;
    double* b = malloc (1000);
    a.length = 1000;
    a.data = b;
    return a;
}

但是,编译器返回:“无效使用灵活数组成员”。

根据“21st Century C”一书,结构中的数据数组作为指针处理(这对我来说非常有意义)。它尚未初始化,因此不应为其分配内存来保存其数据。(甚至编译器也不知道它需要多少内存)。所以我必须分配内存并将其分配给我的返回变量。

那么,为什么编译器会返回错误呢?我该如何解决这个问题?

4

7 回答 7

4

您可以声明data为不完整数组(没有指定维度的数组)或将其声明为指针。(结构中的不完整数组必须是最后一个成员,称为灵活数组成员。)

如果您声明它是一个不完整的数组,则该结构本质上包含该length元素以及您为其分配的尽可能多的数组元素。您必须使用结构的基本大小加上所有元素的空间来分配它,如下所示:

struct data_array *b = malloc(sizeof *b + NumberOfElements * sizeof *b->data);

但是,您不应该返回以这种方式分配的结构,因为无法返回灵活数组的额外元素——函数的返回类型将仅包括结构的基本大小。但是,您可以返回指向该结构的指针。因此,您可以返回b但不能返回*b

如果声明data为指针,则创建结构并分别为data指向的空间分配空间,如下所示:

struct data_array b;
b.length = NumberOfElements;
b.data = malloc(NumberOfElements * sizeof *b.data);

以下是代码示例。首先,使用灵活的数组成员:

struct data_array
{
    long length;
    double data[];
};

struct data_array *test(size_t NumberOfElements)
{
     struct data_array *b = malloc(sizeof *b + NumberOfElements * sizeof *b->data);
     // Put code here to test the result of malloc.
     b->length = NumberOfElements;
     return b;
}

或者用指针:

struct data_array
{
    long length;
    double *data;
};

struct data_array test(size_t NumberOfElements)
{
     struct data_array b = { NumberOfElements,
         malloc(sizeof *b + NumberOfElements * sizeof *b->data) };
     // Put code here to test the result of malloc.
     return b;
}
于 2013-07-18T13:30:46.340 回答
0

我使用 gcc,我认为这种方式可以:

struct data_array {
    long length;
    double* data;
};
struct data_array* test (int length) {
    struct data_array* a =(struct data_array *) malloc (sizeof (data_array));
    a->data = malloc (length*sizeof(double));
    a->length = length;
    return a;
}
于 2013-07-18T15:34:20.783 回答
0
struct data_array * test(long length) {
    struct data_array *a = calloc(1,sizeof(struct data_array) + length*sizeof(double));
    a->length = length;
    return a;
}
于 2013-07-18T13:35:28.047 回答
0

至于不能转换成的原因double*double[]可以参考之前问的这个问题

至于解决问题,改成double data[];就行了double *data;

新更新:

double* b = malloc(sizeof(double) * 1000);
于 2013-07-18T13:26:21.527 回答
0

您正在尝试在行更改数组的基地址

a.data = b;

数组基地址不能修改,数组基地址是一个常量指针。

于 2013-07-18T13:22:38.747 回答
0

像你这样具有灵活数组成员data的结构(结构定义中未给出大小)将像这样分配:

struct data_array *a;   // pointer!!
a = malloc( sizeof(struct data_array) + 1000 * sizeof(double) );

sizeof(struct data_array)您的结构的常量大小在哪里,不包括data并且1000是所需的数组大小。当然,更改data为指针并单独分配它也可以,但这有点不同。

于 2013-07-18T13:30:14.590 回答
0

一些事情:

1)将结构防御更改为:

 struct data_array {
    long length;
    double* data;
          ^
};

2)这就是你应该如何使用 malloc 为你的数组分配内存:

a.data =  malloc (length * sizeof(double));

编辑

错误太多了,就按照这段代码:

#include <stdio.h>
#include <stdlib.h>
struct data_array {
    long length;
    double* data;
};
struct data_array* test (int length) {
    struct data_array* a;
    a = malloc (sizeof (data_array));
    a->data = malloc (length*sizeof(double));
    a->length = length;
    return a;
}

int main () {
    data_array* x;
    x = test (5);
    for (int i=0; i<5; i++) {
        x->data[i] = i+0.5;
    }
    for (int i=0; i<5; i++) {
        printf ("%f\n" , x->data[i]);
    }
}

请注意,在使用 maloc 时您可能需要向类型添加强制转换(我的视觉强迫我这样做,否则会出现编译错误。但它只是磨损了)。

于 2013-07-18T13:31:12.143 回答