“数组类型具有不完整的元素类型”

时间:2013-09-21 21:27:51

标签: c struct circular-dependency

我是C编程新手,并拥有以下代码。我正面临以下错误。

typedef struct Vertex Vertex;
typedef struct Edge Edge;

struct Vertex {
   bool known;
   char id[25];
   Edge edges[20];
   int distance;
};

struct Edge {
   Vertex target;
   int weight;
};

typedef struct {
   Vertex Nodes[20];
   int pass;
   int infinity;
} Graph;

它给出的错误是:

  

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

有人可以帮我理解是什么问题吗?

5 个答案:

答案 0 :(得分:1)

typedef struct Vertex Vertex;
typedef struct Edge Vertex;

这可能会产生一些名称冲突,只需更改其中一个名称即可。

答案 1 :(得分:0)

唯一可行的方法是使用各种指针并解决如何实施VertexEdge结构的问题:

/*your typedefs didn't make sense to me as it was conflicting. So, I edited it accordingly*/
//typedef struct Vertex Vertex;
//typedef struct Edge Vertex;

struct Vertex;
struct Edge;

typedef struct Vertex {
   bool known;
   char id[25];
   struct Edge *edges;//This HAS to be a pointer.
   int distance;
} Vertex;

typedef struct Edge {
   Vertex target;
   int weight;
} Edge;

typedef struct {
   Vertex Nodes[20];
   int pass;
   int infinity;
} Graph;

为什么这样做?因为名为forward declaration的东西:

  

...前向声明是标识符的声明(表示   一个实体,如类型,变量或函数)   程序员还没有给出完整的定义。它是必需的   编译器以了解标识符的类型(内存大小)   分配,类型检查的类型,如函数签名),   但它不是一个特定的值(如果是变量)或   定义(在函数的情况下)......

答案 2 :(得分:0)

  

有人可以帮我理解是什么问题吗?

数组具有以下属性:

  1. 其所有元素都具有相同的大小。
  2. 这些元素是有条不紊地存放的。
  3. 这允许从第一个元素的大小和内存地址以及索引id[i]计算每个元素的内存地址(例如i)。

    为此,编译器需要知道数组元素的大小。声明Vertex::edges[20]成员时,编译器还不知道Edge类型的大对象有多大。因此编译错误。

    避免这种情况的一种方法是,在Edge结构之前定义Vertex结构。在您的情况下,这没有用,因为Edge::target的类型为Vertex,您将收到类似的错误。结构成员的内存地址是使用对象的内存地址计算的,并添加了在请求成员之前的成员大小(可能还有一些填充)。

    在这种循环依赖的情况下,可以使用指针作为成员,因为指向结构的指针具有相同的大小,无论结构具有哪个成员,指针指向。

答案 3 :(得分:0)

在此声明中

struct Vertex {
   bool known;
   char id[25];
   Edge edges[20];
   int distance;
};

尚未声明类型Edge。这里的编译器只知道它对应于struct Edge,但struct本身是未知的。

答案 4 :(得分:0)

考虑一下:编译器必须知道Vertex和Edge结构的大小。如果使“边”包含“顶点”和“顶点”包含“边”,则无法对其进行整理。解决方案是仅提供指向结构的指针(编译器应该知道指针大小)。我会使用jrd1版本进行一些小改动:

struct Edge {
   struct Vertex* target;
   int weight;
} Edge;

typedef struct Vertex {
   bool known;
   char id[25];
   struct Edge edges[20];
   int distance;
} Vertex;

typedef struct {
   Vertex Nodes[20];
   int pass;
   int infinity;
} Graph;

这应该可以正常工作。

此外,如果每个边缘都应该指向顶点所在的位置,那么你真的不需要存储该指针,你可以在linux内核中使用类似container_of宏的东西,如果你想。