0

我是 C 新手,让我发疯的一件事是如何让我的项目的所有文件都可以看到 typedef 结构......也许是设计错误,不确定......

阶段是我有一个像这样的 typedef 结构

// File header.h
typedef struct stu {
    char name[60];
    char id[10];
    int age;
    float puntuation;
} Student;

我有几个数据结构,我想在其中使用这个 typedef,我有一个堆栈、一个哈希表和一个二叉树......我在 main.c 中包含所有

// File main.c
#include "header.h"
#include "hashtable.h"
#include "stack.h"
#include "tree.h"

我需要在哈希表和堆栈中使用学生,还需要使用树中堆栈中定义的另一个 typedef,但我无法让它工作......

编译器在 tree.h 和 tree.c 中说类型名称“stack_def”未知,如果我在 main.c 中排除 stack.h 并将其包含在 tree.h 中,那么它在 stack.h 中对 typedef Student 表示相同。

有人可以告诉我这里发生了什么吗?

谢谢。

4

2 回答 2

1

我的通灵能力告诉我,你的头文件中有一个循环引用——你有两个头文件a.hb.h,其中每个#include是另一个(或者可能是一个更长的链,例如a.h包括b.h,其中包括c.h,其中包括a.h)。

要解决这个问题,您需要删除不必要的包含——只让每个头文件包含正确编译所需的最少的其他头文件。如果您只需要使用指向某些类型的指针(没有完整定义),则可以使用前向声明 而不包括类型:

// Forward declaration of `stu' -- we can now use pointers to `stu', but not
// any of the members of `stu' etc.
struct stu;

// Pointer to `stu' -- OK
struct other_struct
{
    struct stu *a_pointer;
};

// Function parameters and return value of `stu' -- OK
struct stu function_taking_stu_and_returning_stu(struct stu arg);

// `stu' instance -- ERROR
struct another_struct
{
    struct stu not_a_pointer;  // ERROR -- `stu' is incomplete
};

从头文件中删除循环依赖项后,它应该可以正确编译。

于 2013-08-18T19:03:06.243 回答
0

在每个文件中,无论是头文件还是源文件,都使用#include包含声明头文件或源文件需要的东西的每个头文件。例如,如果tree.h使用该Student类型,则在tree.h中放置一个#include包含声明该Student类型的头文件的指令。您不应该猜测这里包含标题。这是一条简单的规则:如果一个文件使用了在头文件中声明的内容,则将该头文件包含在该文件中。

显然,如果每个文件都包含声明文件所需内容的标头,那么文件所需的任何内容都不会被未声明。所以那些编译器错误消息应该消失。

这样做之后,您可能会遇到一个问题是包含循环,其中某些文件包含一个包含第一个文件的标题(可能间接地,通过包含文件链)。在简单的项目中,不应该出现这样的循环;任何标头都不应依赖于声明另一个标头的内容并声明另一个标头需要的内容。但是,如果你有这样的循环,你可以通过使用所谓的“header guards”使第二次包含 header 无效来打破它:

// Test whether this header has not been included before.
#if !defined ThisHeaderFileName_h

// Define a symbol so we know this header has now been included.
#define ThisHeaderfileName_h

… // Put body of the header file here.

// Close the #if.
#endif
于 2013-08-18T19:08:00.297 回答