【问题标题】:C struct - error: unknown type name between two filesC struct - 错误:两个文件之间的未知类型名称
【发布时间】:2018-07-09 13:56:17
【问题描述】:

我有 3 个文件:

-file 1 具有 table1 结构和作用于表 2 结构的函数

// header file table 1
#include "table_2.h" 
typedef struct{...}table1;

void * doSomethingGivenTable2(table2 * t2);

-file 2 具有 table2 结构和作用于表 1 结构的函数

// header file table 2
#include "table_1.h"
typedef struct{...}table2;

void * doSomethingGivenTable1(table1 * t1);

-file 3 使用文件 1 和 2 中的两个结构

#include "table_1.h"
#include "table_2.h" 
// this is fine because I am including both of them in a separate file

文件 3 中发生的情况很好,但文件 1 和文件 2 为结构生成 error: unknown type name,因为我在另一个文件中包含每个文件的标题。我还定义了使用其他结构的函数。我可以在将这两个功能留在原处的同时解决此问题吗?如果没有,那我还有什么选择?

谢谢

【问题讨论】:

  • 显示完整的错误,包括源代码行号。并使用" 包含“自定义”标题。
  • 阅读“前向声明”和“标题包括警卫”。
  • @EugeneSh。我不明白你的意思。我应该在答案或问题中包含“自定义”吗?
  • @DevSolar 谢谢。我会的。
  • Eugene 的意思是 #include <...> 通常保留给标准库头文件,#include "..." 用于其他所有内容。几乎所有编译器都不会在两者之间产生实际差异,但这是一种很好的风格。

标签: c gcc struct


【解决方案1】:

您需要结构标记,以便可以typedef 为不完整的结构类型提供标识符。为避免多次定义相同的typedef 标识符,可以将typedef 声明移动到一个公共头文件中,如下所示:

table_common.h

#ifndef TABLE_COMMON_H_INCLUDED
#define TABLE_COMMON_H_INCLUDED

typedef struct table1 table1;
typedef struct table2 table2;

#endif

table_1.h

#ifndef TABLE_1_H_INCLUDED
#define TABLE_1_H_INCLUDED

#include "table_common.h"

struct table1 {
   ...
};

void * doSomethingGivenTable2(table2 * t2);

#endif

table_2.h

#ifndef TABLE_2_H_INCLUDED
#define TABLE_2_H_INCLUDED

#include "table_common.h"

struct table2 {
   ...
};

void * doSomethingGivenTable1(table1 * t1);

#endif

注意事项

  1. struct table1 中的table1 是一个结构标记。我为结构标记及其关联的typedef 标识符使用了相同的名称。可以使用相同的名称,因为结构标记的命名空间与其他标识符的命名空间不同。但是,结构标记名称不需要与 typedef 标识符匹配,因此您可以根据需要使它们不同。

  2. 我编写的头文件使用了一个通用的预处理器技巧,以避免在多次包含同一个头文件时出现问题。为这个技巧定义的宏被称为“保护宏”。

【讨论】:

    【解决方案2】:

    您可以像这样将typedef 与实际的struct 定义分开。这允许编译器知道table1 是它可以预期找到的数据类型,但稍后会得到它的完整定义,所以不用担心它还不知道它实际上是什么。

    #ifndef TABLE1_H
    #define TABLE1_H
    
    typedef struct table1_s table1;
    
    #include "table2.h"
    
    struct table1_s
      {
      // contents of struct
      };
    
    #endif
    

    顺便说一句,如果您有仅使用(例如)table2 的函数,则应将它们声明在与 table2 相同的包含文件中,而不是 table1

    【讨论】:

      【解决方案3】:

      在对面表的表头中也声明结构名称,比如

      typedef struct table1 table1;

      在 table2.h 内,反之亦然。

      【讨论】:

      • 但我现在就是这种情况。每个都在头文件中定义。我会改变我的问题以反映这一点
      • table1 table1 是错字还是它应该怎么做?因为现在我得到 'table1' 的冲突类型和 table2 的相同
      • @Ahmed 对于同一个标识符,您可能有多个 typedef 声明。请参阅my answer 了解解决方法。
      【解决方案4】:

      您需要使用前向声明。

      在您的文件 1 中,添加以下语句:

      typedef struct tbl2 table2;
      

      在您的文件 2 中,添加以下语句:

      typedef struct tbl1 table1;
      

      在您的文件 3 中,添加以下语句:

      typedef struct tbl1 table1;
      typedef struct tbl2 table2;
      

      这被称为前向声明,它告诉你的编译器这些结构在其他地方可用,不要抱怨。

      【讨论】:

      • 我现在得到这个 -> warning: useless storage class specifier in empty declaration,我认为由于警告,我仍然遇到未知类型的相同错误。澄清一下,我应该把它放在原始声明之前还是之后?
      • typedef struct table2; 除了struct table2; 所做的之外,并没有真正做任何事情。也许您打算声明一个 typedef 名称?
      猜你喜欢
      • 2017-03-23
      • 2018-10-24
      • 2012-02-20
      • 2016-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多