【问题标题】:"array type has incomplete element type"“数组类型的元素类型不完整”
【发布时间】:2013-09-27 02:01:40
【问题描述】:

我是 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;

它给出的错误是:

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

谁能帮我理解问题出在哪里?

【问题讨论】:

  • -1 用于发布屏幕截图的文本。 (应该是一个 Youtube 视频,由 Abba 支持逐行显示您的代码。)
  • @KerrekSB 问题解决了
  • 您的设置毫无意义。与struct Box { struct Box x; };基本相同。
  • @KerrekSB 试着给一些好的反馈,Vertex target; 可能意味着当一个指针。

标签: c struct circular-dependency


【解决方案1】:

想一想:编译器必须知道 Vertex 和 Edge 结构的大小。如果你让 Edge 包含一个 Vertex 并且 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 宏的东西。

【讨论】:

    【解决方案2】:

    谁能帮我理解问题出在哪里?

    数组具有以下属性:

    1. 它的所有元素都具有相同的大小。
    2. 元素是连续存储的。

    这允许根据第一个元素的大小和内存地址以及索引i 计算每个元素的内存地址(例如id[i])。

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

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

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

    【讨论】:

      【解决方案3】:

      在此声明中

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

      Edge 类型尚未声明。这里的编译器只知道会对应一个struct Edge,而struct本身是未知的。

      【讨论】:

        【解决方案4】:

        唯一可行的方法是混合使用指针并解决如何实现 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的东西:

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

        【讨论】:

          【解决方案5】:
          typedef struct Vertex Vertex;
          typedef struct Edge Vertex;
          

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

          【讨论】:

          • 不,这不是答案。没有名称冲突。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-24
          • 2012-04-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多