【问题标题】:Why does my struct have to be declared as a pointer?为什么我的结构必须声明为指针?
【发布时间】:2016-07-04 00:28:07
【问题描述】:

我正在学习如何创建头文件和分离实现,同时也开始学习如何创建链表。我创建了linked_list.hlinked_list.cmain.c 文件。在main.c 中,尝试创建我键入定义的结构时出现错误,除非我将其创建为指针,否则它可以工作。我不明白这是为什么,有人可以解释一下吗?

linked_list.h:

#ifndef LINKED_LIST_H_
#define LINKED_LIST_H_

typedef struct ListNode_ ListNode;

#endif // LINKED_LIST_H_

linked_list.c:

#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"

struct ListNode_ {
    int data;
    ListNode *next;
};

main.c:

#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"

int main() {

    ListNode node1; // why can't I do this?
    ListNode *node2;    // but this works
}

【问题讨论】:

  • 由于main.c 不包含struct ListNode_ 的定义,因此您无法在该翻译单元中创建该类型的对象。
  • 将您的ListNode_ 结构定义移动到.h 文件。请参阅this answer 以了解有关应将哪些信息存储在头文件中的更多信息。
  • @jake 通常你会将在linkedlist中运行的函数放在linkedlist.c中,例如addremove等。在linkedlist.h中你放置结构声明和函数原型声明.
  • “翻译单元”只是一个源文件加上源文件包含的头文件和其他文件的内容。当您要求它编译单个源文件时,它是编译器考虑的完整代码集。

标签: c pointers struct header typedef


【解决方案1】:

这是因为尽管已经声明了 ListNode 和 ListNode_,但只定义了 ListNode_。编译器不知道 ListNode 对象可以包含什么或做什么。

是的,您可以拥有指向 ListNode 的指针。但是,您不能使用它们。尝试输入

//ListNode node1; // why can't I do this?
ListNode *node2;    // but this works
node2->foo();

您将收到关于不完整类型的相同编译错误消息。只需指针存储在某个地方就可以了,因为它毕竟只是一个地址,程序只需要知道它指向什么。

是的,你没有使用 node1,但它仍然给你一个错误。为什么?因为程序将自动为 node1 分配空间,并且它不知道该空间应该是多少。更不用说它应该自动调用它的构造函数,这又是没有定义的。

这也是这里的原因

struct ListNode_ {
    int data;
    ListNode *next;
};

你可以拥有那个指针。

我忽略了文件甚至没有正确链接的事实,因为这已在 cmets 中讨论过,无论如何它与这个问题无关。

【讨论】:

    【解决方案2】:

    由于您使用了多个文件,因此您必须更加小心,以确保所有文件都具有相同的 struct 视图。特别是,您应该考虑在头文件linked_list.h 本身中定义struct ListNodetypedef,如下所示:

    struct Listnode_ {
        int data;
        struct ListNode_ *next;
    };
    
    typedef struct Listnode_ Listnode;
    

    你不能声明实际变量的原因是main.c不知道它的结构是什么,所以它不能为它分配内存。但是,您可以声明一个指针,因为所有指针在内部都具有相同的结构,无论它们是什么类型。这称为PIMPLE 概念(指向实现的指针),您可以在其中声明指向某个实现的指针,即使您不知道它是什么——它是C 提供的一种抽象形式。

    【讨论】:

      【解决方案3】:

      当您在main.c 中声明ListNode 时,您需要考虑编译器会做什么。它看到了struct ListNode_ 的typedef,但它在编译main.c 时不知道struct ListNode_ 是什么。要解决此问题,您需要将struct ListNode_ 的定义移动到linked_list.h

      声明指向ListNode 的指针是可行的,因为可以声明一个指向未知大小对象的指针,例如本例中的struct ListNode_。然而,如果你想声明一个完整的ListNode,编译器需要知道它的大小。但是由于编译器是单独编译各个源文件的,所以不知道linked_list.c中的struct ListNode_,从而报错。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-30
        • 2010-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多