【发布时间】:2021-02-28 23:26:44
【问题描述】:
我是 C 语言的新手,但已经获得了一些经验。现在我正在使用(或多或少)复杂的数据结构(例如 Map(我将使用 Maps 作为示例))创建更大的项目。由于我希望我的数据结构代码可在未来的项目中重复使用,因此我喜欢它们相当通用且位于单独的文件中。
由于 C 不使用/没有泛型(如 Java)或模板(如 C++)或任何类似的概念,我考虑过使用全局定义的数据类型,如
typedef union {
int integer;
char * str;
// etc.
} data_t;
并将其放入main.h 中,该main.h 将包含在所有其他(头)文件中(可能使用警卫)。这对我来说效果很好,但是……
有没有办法将数据结构集成到我的data_t(包括main.h 以使用data_t)?
简单但显然不起作用(由于循环包含)的解决方案是 #include "map.h" 在 main.h 同时还包括 main.h 在 map.h;如前所述,由于显而易见的原因,这不起作用。
基本上我想要一个可以容纳其他地图的地图,同时只使用一个data_t 和一个地图实现。跟踪我所在的“层”将在周围的程序中完成(或者我可以在data_t 中添加一些关于其类型的信息,这不是这里的重点)。
我知道仅使用void * 就可以做到这一点;但如果我不需要的话,我不希望对原始数据类型(如 int)进行不必要的引用。
有什么干净的方法来做这种行为吗?
谢谢!
(如果需要任何实际代码,请告诉我)
实际代码
main.h 我想包含像我的data_t 这样的一般声明:
#ifndef _MAIN_H_
#define _MAIN_H_
#include "map.h"
typedef union {
int integer;
char * str;
map_t map;
} data_t;
#endif
map.h:
#ifndef _MAP_H_
#define _MAP_H_
#include "main.h"
typedef char * key_t;
typedef struct {
int (*hash_f)(key_t);
int size;
data_t * data;
} map_t;
int map_init(map_t * map, int (*hash_f)(key_t key));
int map_put(map_t map, key_t key, data_t data);
int map_get(map_t map, key_t key);
#endif
用make编译:
% make
gcc -Wall -Wextra -Wpedantic -g -c main.c -o build/main.o
In file included from main.c:1:
./main.h:8:5: error: unknown type name 'map_t'
map_t map;
^
1 error generated.
make: *** [build/main.o] Error 1
【问题讨论】:
-
请举例说明
map.h中的内容。为什么它需要main.h?也就是说,给出一个具体而完整的代码示例来说明您正在尝试做什么。用文字描述事物很少准确或清晰。 -
对于特定的 stackoverflow 答案,您的问题可能过于宽泛。但无论如何,C 没有模板。对于模板,请使用 C++。
-
C 中的通用代码有两个选择是宏和 void *(第三个选项是外部代码生成)。
-
如果您正在寻找避免在多个头文件和包装函数中使用数据类型的选项,则不清楚您在这里面临的确切问题是什么。使用“void*”来跨函数传递地址,并在需要的函数定义中将数据类型转换为所需的格式。并且只在“.c”文件中包含“.h”文件。
-
在 C++ 中,您将具有相同的循环依赖关系,因为我了解您的问题。请给我们一个具体的例子(edit你提问并添加它),即使它不会编译。
标签: c project header-files