C 具有2种不同密钥类型和最少冗余代码的树数据结构

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 {

我正在用C编写一个前缀树来存储IP前缀。 密钥是IP前缀。 我想将其与32位或128位密钥(IPv4/IPv6地址)一起使用

插入/删除/查找函数需要为ipv4或ipv6变体调用不同的bitop函数

我怎么能用C来做这个

  • 密钥的类型不应在运行时确定
  • 我想编译成不同版本的数据结构,一个使用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位地址是一个巨大的内存浪费(几十万个节点)