GCC:数组类型具有不完整的元素类型

rryofs0p  于 2023-10-19  发布在  其他
关注(0)|答案(3)|浏览(143)

我已经声明了一个struct,并试图将这些结构体的数组(以及双精度型的double数组和一个整数)传递到函数中。当我编译它的时候,我从gcc得到一个 “数组类型有不完整的元素类型” 的消息。我在传递struct给函数的过程中有什么错误吗?

typedef struct graph_node {
  int X;
  int Y;
  int active;
} g_node;

void print_graph(g_node graph_node[], double weight[][], int nodes);

我也试过struct g_node graph_node[],但我得到了同样的东西。

xfyts7mz

xfyts7mz1#

是这个阵列造成了麻烦:

void print_graph(g_node graph_node[], double weight[][], int nodes);

必须给出第二个和随后的尺寸:

void print_graph(g_node graph_node[], double weight[][32], int nodes);

或者你可以只给指针给予一个指针:

void print_graph(g_node graph_node[], double **weight, int nodes);

然而,虽然它们看起来相似,但它们的内部却非常不同。
如果你使用C99,你可以使用可变限定数组。引用C99标准的一个例子(第6.7.5.2节数组声明符):

void fvla(int m, int C[m][m]); // valid: VLA with prototype scope

void fvla(int m, int C[m][m])  // valid: adjusted to auto pointer to VLA
{
    typedef int VLA[m][m];     // valid: block scope typedef VLA
    struct tag {
        int (*y)[n];           // invalid: y not ordinary identifier
        int z[n];              // invalid: z not ordinary identifier
    };
    int D[m];                  // valid: auto VLA
    static int E[m];           // invalid: static block scope VLA
    extern int F[m];           // invalid: F has linkage and is VLA
    int (*s)[m];               // valid: auto pointer to VLA
    extern int (*r)[m];        // invalid: r has linkage and points to VLA
    static int (*q)[m] = &B;   // valid: q is a static block pointer to VLA
}

评论中的问题

[...]在main()中,我试图传递给函数的变量是double array[][],那么我如何将其传递给函数呢?将array[0][0]传递给它会产生不兼容的参数类型,就像&array&array[0][0]一样。
main()中,变量应该是:

double array[10][20];

或类似的东西;也许

double array[][20] = { { 1.0, 0.0, ... }, ... };

你应该可以用这样的代码来传递它:

typedef struct graph_node
{
    int X;
    int Y;
    int active;
} g_node;

void print_graph(g_node graph_node[], double weight[][20], int nodes);

int main(void)
{
    g_node g[10];
    double array[10][20];
    int n = 10;

    print_graph(g, array, n);
    return 0;
}

这可以用GCC 4.2(i686-apple-darwin 11-llvm-gcc-4.2(GCC)4.2.1(基于Apple Inc. build 5658)(LLVM build 2336.9.00)),以及在Mac OS X 10.7.3上使用命令行的GCC 4.7.0:

/usr/bin/gcc -O3 -g -std=c99 -Wall -Wextra -c zzz.c
qxsslcnc

qxsslcnc2#

编译器需要知道二维数组中第二维的大小。举例来说:

void print_graph(g_node graph_node[], double weight[][5], int nodes);
chhkpiq4

chhkpiq43#

张贴这一点,以防有人遇到这个问题,并想知道为什么[]的工作和[][]不正式的原因,一般来说。游戏中有各种规则:什么是有效的数组声明的规则,以及数组作为参数传递给函数的规则如何“衰减”为指向第一个元素的指针。
C17 6.7.6.2/1数组声明符:
元素类型不能是不完整或函数类型。
double weight[][]的情况下,元素类型是double[],一个不完整的(数组)类型,不允许在任何地方声明,参数与否。因为这个数组声明规则在函数参数的“数组衰减”规则之前应用,这在C17 6.7.6.3/7函数声明符中找到:
将参数声明为“类型数组”应调整为“类型限定指针”
该规则假设我们已经有了数组的声明,这必须根据前面引用的6.7.6.2规则来完成。
在一维数组double[]的情况下,这是一个不完整的数组类型,但元素类型是double,这是一个完整的类型。根据C17 www.example.com允许这样的数组声明6.7.6.2/4:
如果不存在大小,则数组类型是不完整类型。
每当这样的数组与初始化器列表一起使用时,double foo[] = { 1.0f };然后C17 6.7.9/22声明它的大小取决于初始化器,并在声明结束时变成一个完整的类型:
如果初始化一个未知大小的数组,则其大小由具有显式初始化式的最大索引元素确定。数组类型在其初始值设定项列表的末尾完成。
如果它没有被初始化,而只是函数参数列表的一部分,那么前面提到的“数组衰减”规则适用,double[]double*替换。
现在,如果我们有一个数组参数,如double [][3],那么它是一个不完整的数组类型,但元素类型double [3]是一个完整的数组类型,所以它是一个有效的声明。在这种情况下,参数被调整为指向这样的元素类型double (*)[3]的指针。这就是为什么多维数组参数声明中最左边的数组维度可以省略的原因-实际上,我们在那里输入什么大小并不重要。

相关问题