【问题标题】:Use typedef from one header in another and vice versa在另一个标题中使用 typedef,反之亦然
【发布时间】:2021-04-07 08:55:56
【问题描述】:

假设我有这样一个项目结构:

main.c

#include "hashtable.h"
#include "list.h"

int main()
{
    hash_table ht = calloc(1, sizeof(htable));
    cmp_function f;
    TLDI list;
    return 0;
}

hashtable.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef _HASH_TABLE_
#define _HASH_TABLE_
#include "list.h"

typedef int (*hash_function)(void*, int);

typedef struct _hasht_{
  int maxElemNumber;
  hash_function hf;
  TLDI* key_array;
} htable, *hash_table;

void test2(cmp_function cmp);

#endif

list.h

#include "hashtable.h"

#ifndef _LINKED_LIST_
#define _LINKED_LIST_

typedef int (*cmp_function)(void*, void*);

typedef struct _node_ {
  void *info;
  struct _node_ *pre, *urm;
} TNode, *TLDI;

int test(hash_table ht);

#endif

还有另外两个 C 文件:

hash_func.c

#include "hashtable.h"

void test2(cmp_function cmp)
{
    printf("test\n");
}

list_func.c

#include "list.h"

int test(hash_table ht)
{
    return 1;
}

我想在hashtable.h 中使用来自list.h 的typedef,它是typedef struct...},*TLDI;。同样,list.h 使用来自hashtable.htypedef struct ...},*hash_table;。我可以做这样的事情还是我错了?因为编译整个项目时出现此错误:

In file included from hashtable.h:7,
                 from main.c:1:
list.h:14:10: error: unknown type name ‘hash_table’
   14 | int test(hash_table ht);
In file included from hashtable.h:7,
from hash_func.c:1:
list.h:14:10: error: unknown type name ‘hash_table’
   14 | int test(hash_table ht);

我不擅长typedef 和标题,但如果我能得到这个问题的答案,或者至少能找到一个可以找到更多关于它们的来源,我将非常感激。

【问题讨论】:

  • 我只是希望人们停止使用 typedef。停止在头文件中隐藏逻辑。但是,如果您真的需要,请仅使用类型定义创建第三个头文件,并将其包含在其他头文件中。然而,我真的很担心你在 list.h 中包含 hash_table.h,这根本没有意义。
  • 你不能有相互递归的头文件。将您的 test 函数提取到不同的标题中,这样就没有循环依赖。或者,您可以解决结构的前向声明。

标签: c header project typedef


【解决方案1】:

如果格式正确,两个相互依赖的标题不会成为阻碍。我观察到的是,您的包含保护没有包含完整的标题,而只是其中的一部分,我认为这是错误的。正确使用包含守卫的方法如下所示

示例标题some_component.h:

#ifndef SOME_COMPONENT_H
#define SOME_COMPONENT_H

// include whatever you need here (*after* the opening guard):
#include "some_other_component.h"

// start type definitions and declarations *after* includes:
struct some_component_t {
  // ...
};

#endif

这样,您的标题将最一致地工作:

  • 要么完整阅读
  • 或完全忽略

我建议您避免在包含之前放置定义,因为这允许您修改包含内容的内容。起初看起来很诱人的想法,在绝大多数情况下会变成一个令人困惑的长期噩梦

另外一点是,如果两个头文件中的定义真的相互依赖,你应该重新考虑你的设计。

另外,不清楚为什么依赖cmp_functionvoid test2(cmp_function cmp);hashtable.h中声明,为什么依赖hash_tableint test(hash_table ht);list.h中声明;对我来说,这似乎是你在这里混淆了东西。换句话说,通过交换一些声明的位置,你就可以摆脱大部分的纠缠。

您还应该知道typedefs 和incomplete types 上允许使用指针,因此可以声明指向尚未定义的结构的指针。因此,例如,following compiles:

typedef int (*hash_function)(void*,int);
typedef int (*cmp_function)(void*,void*);

typedef struct _hasht_ hasht, *hash_table;
typedef struct _node_ TNode, *TLDI;

struct _node_ {
  void *info;
  struct _node_ *pre, *urm;
};

struct _hasht_{
  int maxElemNumber;
  hash_function hf;
  TLDI* key_array;
};

...作为does this(版本没有structtypedefs):

struct _node_ {
  void *info;
  struct _node_ *pre, *urm;
};

typedef int (*hash_function)(void*,int);

struct _hasht_{
  int maxElemNumber;
  hash_function hf;
  struct _node_** key_array;
};

【讨论】:

    【解决方案2】:

    标题的整体相互依赖性有点难看,但可以通过一些前向声明来纠正错误:

    hashtable.h

    #ifndef _HASH_TABLE_
    #define _HASH_TABLE_
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct _hasht_ htable, *hash_table;
    typedef int (*hash_function)(void*,int);
    
    #include "list.h"
    
    struct _hasht_ {
        int maxElemNumber;
        hash_function hf;
        TLDI* key_array;
    };
    
    void test2(cmp_function cmp);
    
    #endif
    

    list.h

    #ifndef _LINKED_LIST_
    #define _LINKED_LIST_
    
    typedef struct _node_ TNode, *TLDI;
    typedef int (*cmp_function)(void*,void*);
    
    #include "hashtable.h"
    
    struct _node_ {
        void *info;
        struct _node_ *pre, *urm;
    };
    
    int test(hash_table ht);
    
    #endif
    

    【讨论】:

      猜你喜欢
      • 2019-02-19
      • 2017-10-16
      • 2022-11-04
      • 1970-01-01
      • 2013-02-16
      • 2018-03-20
      • 2020-08-28
      • 1970-01-01
      • 2016-09-11
      相关资源
      最近更新 更多