【问题标题】:undefined C struct forward declaration未定义的 C 结构前向声明
【发布时间】:2010-10-11 21:42:03
【问题描述】:

我有一个头文件 port.h、port.c 和我的 main.c

我收到以下错误:“ports”使用未定义的结构“port_t”

我认为我已经在 .h 文件中声明了结构并且在 .c 文件中具有实际结构是可以的。

我需要前向声明,因为我想在我的 port.c 文件中隐藏一些数据。

在我的 port.h 中,我有以下内容:

/* port.h */
struct port_t;

port.c:

/* port.c */
#include "port.h"
struct port_t
{
    unsigned int port_id;
    char name;
};

main.c:

/* main.c */
#include <stdio.h>
#include "port.h"

int main(void)
{
struct port_t ports;

return 0;
}

非常感谢您的任何建议,

【问题讨论】:

  • 请注意,一个字符的端口名称不会很令人兴奋!

标签: c struct declaration forward


【解决方案1】:

不幸的是,编译器在编译 main.c 时需要知道port_t 的大小(以字节为单位),因此您需要头文件中的完整类型定义。

【讨论】:

  • 显然你是对的。 C 的处理方式似乎与 C++ 完全不同。
  • @litb:你是什么意思?我相信在 c++ 中,main.cpp 仍然需要 port_t 的完整定义才能创建“ports”实例。
  • @Matthew:可能值得澄清的是,头文件中需要完整的 type 定义;变量定义在源文件中。
  • 史蒂夫是正确的,当然。 C++ 是一样的,即使是类。您需要头文件中的完整类定义,以便编译器知道它应该在堆栈上为该类型的变量保留多少空间。只有成员函数的实现不需要在头文件中。
  • 埃文,在 C 中它不是一个结构定义,而是一个结构声明,如果你做 struct f { ... };在 C++ 中,这称为定义,在 C 中,结构定义和结构声明之间没有这种区别:两者都是声明。第一个 ("struct f;") 声明了一个不完整的类型...
【解决方案2】:

如果您想隐藏port_t 结构的内部数据,您可以使用标准库如何处理FILE 对象的技术。客户端代码只处理FILE* 项目,因此他们不需要(实际上,然后通常不能)知道FILE 结构中的实际内容。这种方法的缺点是客户端代码不能简单地将变量声明为该类型 - 它们只能具有指​​向它的指针,因此需要使用某些 API 创建和销毁对象,并且 all 对象的使用必须通过一些 API。

这样做的好处是你有一个干净的接口来告诉你必须如何使用port_t 对象,并让你保持私有的东西私有(非私有的东西需要 getter/setter 函数让客户端访问它们)。

就像在 C 库中处理 FILE I/O 的方式一样。

【讨论】:

  • 甚至 FILE 结构在 stdio.h 中也有清晰的布局。至少,在我的系统上。 “typedef 结构 __sFILE { ... } 文件;”通过 FILE 指针,我们永远不需要查看它们的内部结构(这非常有趣 - 用于如何读取/写入/等的函数指针),但它们仍然存在。
  • 另请注意:要处理 FILE * 指针而不是 struct FILE * 指针,您需要使用“typedef”版本。上面的代码需要“struct port_t”。如果它是“typedef struct port_t { ... } PORT”,那么它可以使用类似于 FILE * 指针的 PORT * 指针。
  • @Chris,它不必完全声明,实现可以在技术上将 FILE 结构定义为 char[X] 因为标准中没有任何内容规定结构包含的内容 - 所以它可以隐藏起来。
  • 但是,Chris 是对的,看来我所有的编译器都具有在 stdio.h 中定义的完整 FILE 结构。我一直认为他们不会 - 我想知道是否有什么让他们不得不这样做,或者它是否只是方便并且实施者并不关心结构是否完全可用。
  • 在 中布置文件结构的原因是可以定义像 getchar() 这样的宏 - 编译器需要内部结构。
【解决方案3】:

我使用的一个常见解决方案:

/* port.h */
typedef struct port_t *port_p;

/* port.c */
#include "port.h"
struct port_t
{
    unsigned int port_id;
    char name;
};

您在函数接口中使用 port_p。 您还需要在 port.h 中创建特殊的 malloc(和免费)包装器:

port_p portAlloc(/*perhaps some initialisation args */);
portFree(port_p);

【讨论】:

    【解决方案4】:

    我会推荐一种不同的方式:

    /* port.h */
    #ifndef _PORT_H
    #define _PORT_H
    typedef struct /* Define the struct in the header */
    {
        unsigned int port_id;
        char name;
    }port_t;
    void store_port_t(port_t);/*Prototype*/
    #endif
    
    /* port.c */
    #include "port.h"
    static port_t my_hidden_port; /* Here you can hide whatever you want */
    void store_port_t(port_t hide_this)
    {
        my_hidden_port = hide_this;
    }
    
    /* main.c */
    #include <stdio.h>
    #include "port.h"
    int main(void)
    {
        struct port_t ports;
        /* Hide the data with next function*/
        store_port_t(ports);
        return 0;
    }
    

    在头文件中定义变量通常不好。

    【讨论】:

    • 他没有在标头中定义变量,他试图转发声明 port_t 类型。
    • 为什么他不使用 get/set 或 simulair 函数让我很失望...但是你是对的...我只是给个建议...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 2013-04-02
    相关资源
    最近更新 更多