C 从一个标题到另一个标题使用typedef,反之亦然

C 从一个标题到另一个标题使用typedef,反之亦然,c,header,project,typedef,C,Header,Project,Typedef,假设我有这样一个项目结构: 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 <stdli

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

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
和另外两个C文件:

hash_func.c

#include "hashtable.h"

void test2(cmp_function cmp)
{
    printf("test\n");
}
#include "list.h"

int test(hash_table ht)
{
    return 1;
}
list_func.c

#include "hashtable.h"

void test2(cmp_function cmp)
{
    printf("test\n");
}
#include "list.h"

int test(hash_table ht)
{
    return 1;
}
我想在
hashtable.h
中使用
list.h
中的typedef,它是
typedef struct…},*TLDI。同样地,
list.h
使用一个
typedef struct…}、*hash_表来自
hashtable.h
。我可以这样做吗?否则我错了?因为我在编译整个项目时遇到此错误:

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
和标题不太在行,但如果我能得到这个问题的答案,或者至少能从中找到更多关于它们的信息,我将不胜感激。

如果格式正确,两个相互依赖的标题就不会成为阻碍展示的因素。我所观察到的是,你的包括守卫没有封闭整个标题,而只是其中的一部分,我认为这是错误的。使用包含防护装置的正确方法如下所示

示例标题
某些组件.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
通过这种方式,您可以最稳定地工作:

  • 要么通读
  • 还是完全被忽视
我建议您避免将定义放在包含之前,因为这样可以修改包含内容的内容。起初看似诱人的想法,从长远来看,在绝大多数情况下会变成令人困惑的噩梦

另一点是,如果两个标题中的定义真的相互依赖,您应该重新考虑您的设计

另外,还不清楚为什么
voidtest2(cmp\u函数cmp)cmp\u函数的code>在
hashtable.h
和why
int test(hash\u table ht)中声明哈希表的code>在
列表中声明;在我看来,这好像是你把事情搞混了。换言之,通过切换某些声明的位置,可以消除大部分纠缠

您还应该知道,允许启用
typedef
s和指针,因此可以声明指向尚未定义的结构的指针。因此,例如:

。。。as(不带结构的版本):


标头的总体相互依赖性有点难看,但可以通过一些正向声明更正错误:

哈希表.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
#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

我只是希望人们停止使用typedef。停止在头文件中隐藏逻辑。但是,如果确实需要,可以使用类型定义创建第三个头文件,并将其包含在其他头文件中。然而,我真诚地担心您将hash_table.h包含在list.h中,这毫无意义。您不能拥有相互递归的头文件。将
test
函数提取到不同的头中,这样就没有循环依赖关系。或者,您可以处理结构的正向声明。
#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