在另一个 header 中使用 typedef,反之亦然

Use typedef from one header in another and vice versa

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

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.h 中的 typedef 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 和 headers 方面不强,但如果我能得到这个问题的答案,或者至少能从中找到更多关于它们的信息,我会非常感谢。

如果well-formed,两个相互依赖的 header 不是表演障碍。我观察到你的包含守卫没有包含完整的 header 而只是其中的一部分,我认为这是错误的。正确使用 include guards 的方法如下

示例 header 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

这样,你们 header 的工作将最稳定:

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

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

还有一点,如果两个header中的定义真的相互依赖,你应该重新考虑你的设计。

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

您还应该知道 typedefs 和指针在 incomplete types, so it's possible to declare a pointer to a structure that is not yet defined. So, for example, the 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;
};

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

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