C 具有2种不同密钥类型和最少冗余代码的树数据结构
我正在用C编写一个前缀树来存储IP前缀。 密钥是IP前缀。 我想将其与32位或128位密钥(IPv4/IPv6地址)一起使用 插入/删除/查找函数需要为ipv4或ipv6变体调用不同的bitop函数 我怎么能用C来做这个C 具有2种不同密钥类型和最少冗余代码的树数据结构,c,generics,tree,C,Generics,Tree,我正在用C编写一个前缀树来存储IP前缀。 密钥是IP前缀。 我想将其与32位或128位密钥(IPv4/IPv6地址)一起使用 插入/删除/查找函数需要为ipv4或ipv6变体调用不同的bitop函数 我怎么能用C来做这个 密钥的类型不应在运行时确定 我想编译成不同版本的数据结构,一个使用IPv4前缀,另一个使用IPv6前缀 我以后需要在同一个C文件中使用树中的两个版本 我想有最小的重复代码 最后,我希望有以下结构和函数: typedef struct tree_node6_t {
- 密钥的类型不应在运行时确定
- 我想编译成不同版本的数据结构,一个使用IPv4前缀,另一个使用IPv6前缀
- 我以后需要在同一个C文件中使用树中的两个版本
- 我想有最小的重复代码
typedef struct tree_node6_t {
ipv6_addr prefix;
u_int8_t len;
struct tree_node6_t* parent;
struct tree_node6_t* lchild;
struct tree_node6_t* rchild;
void* data;
} tree_node6;
typedef struct tree_node4_t {
ipv4_addr prefix;
u_int8_t len;
struct tree_node4_t* parent;
struct tree_node4_t* lchild;
struct tree_node4_t* rchild;
void* data;
} tree_node;
void tree_insert4(tree_node* root, tree_node* new_node, const unsigned int level);
void tree_insert6(tree_node* root, tree_node* new_node, const unsigned int level);
tree_node* tree_lookup4(const tree_node* root_node, const ipv4_addr* prefix, const u_int8_t prefix_len, unsigned int* level);
tree_node* tree_lookup6(const tree_node* root_node, const ipv6_addr* prefix, const u_int8_t prefix_len, unsigned int* level);
感谢您的提示:=)您可以使用每个IPv4地址都可以映射到IPv6地址的事实。您可以使用另一个typedef来声明ip类型。
然后,您可以在编译时使用预处理器指令更改它:
#ifdef USE_NODE4
typedef ipv4_addr ADDRESSTYPE ;
#define TREEINSERT tree_insert4
#define TREELOOKUP tree_lookup4
#else
typedef ipv6_addr ADDRESSTYPE ;
#define TREEINSERT tree_insert6
#define TREELOOKUP tree_lookup6
#endif
typedef struct tree_node_general {
ADDRESSTYPE prefix;
u_int8_t len;
struct tree_node_general* parent;
struct tree_node_general* lchild;
struct tree_node_general* rchild;
void* data;
} tree_node;
void TREEINSERT (tree_node* root, tree_node* new_node, const unsigned int level);
tree_node* TREELOOKUP (const tree_node* root_node, const ADDRESSTYPE* prefix, const u_int8_t prefix_len, unsigned int* level);
如果您想在编译时完成所有工作,那么使用define-tricky可能是一种方法。我将编译一个具有相同名称的函数,例如使用不同定义集的tree_insert两次。但是,我不能将一个程序链接到两个对象文件,因为tree_insert的符号名是相等的?解决这个问题最简单的方法是为每个文件定义一个不同的名称空间。对,我忘了这一点。您可以使用两个不同名称的单独DLL,并显式导入函数。或者,将方法名称也放在#define中:
#define TREEINSERT tree_insert4
如果我将函数名称也放在define中,我还必须为tree_insert4和tree_insert6编写重复的代码。我可以将define的值附加到函数名吗?是的,但是在128位整数中存储32位地址是一个巨大的内存浪费(几十万个节点)