【问题标题】:How to use the same structure accross multiple source files?如何在多个源文件中使用相同的结构?
【发布时间】:2017-05-20 12:27:42
【问题描述】:

我有 3 个源文件:matrix.c、tetramino.c 和 learntris.c(包括标题 tetramino.hmatrix.h,将其与各自的文件链接)。我有一个结构:所有这些文件都需要struct tetramino。在阅读了这个问题及其答案-How to use a defined struct from another source file? 后,我创建了一个头文件structure.h,现在我的文件如下所示:

在结构.h中:

typedef struct tetramino  
{
  int type;
  char *p;
}tetramino;

在matrix.h中:

#include"structure.h"
int print_matrix(void);
int clear_matrix(void);

在 tetramino.h 中:

#include"structure.h"
int rotate(void);
int set_tetramino(void);

最后,在主 learntris.c 文件中包含:

#include"structure.h"
#include"matrix.h"
#include"tetramino.h"

现在,在编译它们时,我得到了这些错误:

错误:重新定义 'struct tetramino'

错误:'tetramino' 的类型冲突

问题出在哪里?

【问题讨论】:

    标签: c struct compilation header-files


    【解决方案1】:

    当您在所有文件中#include <structure.h> 时,它每次都会包含它们。这会导致它每次都尝试定义结构。

    使用包含保护来确保头文件将被包含一次。

    #ifndef STRUCTURE_H
    #define STRUCTURE_H
    
    typedef struct tetramino  
    {
      int type;
      char *p;
    }tetramino;
    
    #endif /* STRUCTURE_H */
    

    建议在所有头文件中都使用保护,但这不是必须的,而是一个非常好的做法。


    正如 Neroku 所说,您可以改用 #pragme once。阅读更多here

    【讨论】:

    • 使用 #pragma once 作为 include guard 代替
    【解决方案2】:

    除了守卫之外,其他答案解释说,将 .h 文件包含在 .h 文件中并不是一个好习惯,因为您现在无法控制包含它们的顺序。此外,对 .h 文件的更改现在可能导致所有 c 文件需要重新编译,即使它们不受更改的影响(即,您创建了不必要的依赖项)。

    您应该在 C 文件中包含 structure.honly,然后 only 在 C 文件需要了解结构时包含。

    【讨论】:

    • "只有当它需要了解结构时"- 你能详细说明你的意思吗?
    • “不包含 .h 文件的好习惯”- 那么这些文件究竟可以包含什么?
    • "无法控制它们被包含的顺序"- 不是先命名的文件,也是先包含的吗?我的意思是如果我在#include"matrix.h" 之前写#include"structure.h",是不是意味着struct.h 会在matrix.h 之前被包含?
    • “无法控制包含它们的顺序”是指某些 C 文件可能需要与其他 C 文件不同的 .h 文件包含顺序。
    【解决方案3】:

    #include 将包含文件的内容直接粘贴到#include 指令的位置。所以在你的例子中,你最终得到了 3 次相同的结构声明。

    对此的规范解决方案是守卫宏:

    #ifndef EXAMPLE_HEADER_FILE_H
    #define EXAMPLE_HEADER_FILE_H
    
    struct exampleStruct
    {
        // ...
    };
    
    #endif
    

    这样,只有第一个#include 会实际粘贴声明,每个连续的#include 都会导致预处理器跳过整个标头,因为已经定义了保护宏。

    【讨论】:

    • 但是所有这些头文件也包含#include<stdio.h>#include<stdlib.h>。他们为什么不产生任何错误?
    • 因为所有标准头文件也在需要的地方使用了保护宏?
    【解决方案4】:

    每个头文件should have the following structure:

    #ifndef TETRAMINO_STRUCTURE_H
    #define TETRAMINO_STRUCTURE_H
    
    struct tetramino { ... };
    
    #endif
    

    这意味着头文件的主要部分只被评估一次。名称TETRAMINO_STRUCTURE_H由项目名称、文件名和尾部H组成,意思是header

    其次,由于函数声明不需要tetramino 类型,因此您不需要在其中添加#include "structure.h"。您只需要在相应的.c 文件中使用这些行。

    【讨论】:

    • "每个头文件都需要以下结构:" -- 没有。虽然这是最常见的用例,但没有保护宏的标头也有一些很好的用途。
    • 同意,我的回答太简单了。但是初学者按照这个建议,不会对他们造成太大的伤害,所以我觉得没问题。
    • 这当然是对初学者的好建议,我只是将其改写为“您应该始终使用以下 [...]”,所以这不是“糟糕的简化”(使它不正确的那个):)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    相关资源
    最近更新 更多