C两个函数合二为一,带有强制转换

时间:2012-06-06 16:15:53

标签: c casting

我有两个函数完全相同,但是在两个不同类型的struct中,这两种类型的struct非常相似。

想象一下,我有这两个结构。

typedef struct nodeOne{
    Date *date;
    struct nodeOne *next;
    struct nodeOne *prev;
}NodeOne;

typedef struct nodeTwo{
    Date *date;
    struct nodeTwo *next;
    struct nodeTwo *prev;
}NodeTwo;

由于我破坏每个列表的函数几乎是相同的(只是参数的类型不同)我想只做一个函数来制作两个变量。

我有这两个功能

void destroyListOne(NodeOne **head, NodeOne **tail){
    NodeOne *aux;

    while (*head != NULL){
        aux = *head;
        *head = (*head)->next;
        free(aux);
    }
    *tail = NULL;
}

和这一个:

void destroyListTwo(NodeTwo **head, NodeTwo **tail){
    NodeTwo *aux;

    while (*head != NULL){
        aux = *head;
        *head = (*head)->next;
        free(aux);
    }
    *tail = NULL;
}

由于它们非常相似,我想这样做:

void destroyList(void **ini, void **end, int listType){

    if (listType == 0) {
        NodeOne *aux;
        NodeOne head = (NodeOne) ini;
        NodeOne tail = (NodeOne) ed;

    }
    else {
        NodeTwo *aux;
        NodeTwo head = (NodeTwo) ini;
        NodeTwo tail = (NodeTwo) ed;
    }

    while (*head != NULL){
        aux = *head;
        *head = (*head)->next;
        free(aux);
    }
    *tail = NULL;
}

正如您现在可能无法正常工作,但我想知道是否可以实现这一目标。

我必须保持两种结构。

4 个答案:

答案 0 :(得分:2)

正如@Dancrumb所说,这里有一些设计问题,我不建议你做你想做的事。

也就是说,如果nodeOnenodeTwo 总是相同(我会< strong>从不依赖于生产代码。)

您可以选择一个,并始终投射到它(颤抖)。因为它们是具有不同名称的相同结构,所以演员工作:

void destroyList(void *ini, void *end, int listType){

    NodeOne *aux = NULL;
    NodeOne **head = ini;
    NodeOne **tail = end;

    while (*head != NULL){
        aux = *head;
        *head = (*head)->next;
        free(aux);
    }
    *tail = NULL;
}

另请注意,在C中,您不需要显式强制转换,因为void *可以在没有强制转换的情况下隐式转换为任何其他指针类型。

但严重的是,请不要这样做。它脆弱,不可维护,容易出错。

<小时/> 看了@Torp的回答后,我想详细说明问题的精神和答案。有了@Torp代码的错误修复(它没有编译,并且有几个指针问题),它可以使其工作。也就是说,我仍然认为你不应该让它发挥作用。

特别是当我们谈论C(而不是C ++)时,我肯定会将destroy函数分开用于单独的列表类型。尽可能避免使用剪切和粘贴代码,但在这种情况下,我认为安全性,清晰度和可维护性都是赢家。我的意见当然。您的里程可能会有所不同:)

答案 1 :(得分:2)

尽管我不愿意这样说,但这就是为什么模板是用C ++发明的。你确定你不能使用它吗?

这样的事情应该有效:

void destroyList(void **ini, void **end, int listType)
{
    void *aux;
    void *head = ini;
    void *tail = end;


    while (*head != NULL){
        if (listType == 0) {
           aux = (NodeOne *)*head;
           *head = ((NodeOne*)*head)->next;
           free((NodeOne*)aux;
        } else {
           ... same thing with casts to NodeTwo* ...
        }
    }
    *tail = NULL;
}

我不确定我是否将所有类型的演员阵容放在任何地方,但你明白了。

答案 2 :(得分:0)

如果我正在设计这个,我已经完成了:

typedef struct node{
    Date *date;
    struct node *next;
    struct node *prev;
} Node;

由于NodeOneNodeTwo相同,为什么有两种不同的类型?

如果有某些原因导致我失踪,那么我会延伸:

typedef struct nodeOne {
    Node nodeInfo;
    /* additional */
} NodeOne

typedef struct nodeTwo {
    Node nodeInfo;
    /* additional */
} NodeTwo

然后,只需将nodeInfo字段传递给Node操作函数。

答案 3 :(得分:0)

编写一个包含所有函数的#define,只需将函数名和结构类型作为参数。

#define DECLARE_DESTRUCTION_FUNCT(_name_, _type_) void _name_(_type_ **head, _type_ **tail){\
_type_ *aux;\
\
while (*head != NULL){\
    aux = *head;\
    *head = (*head)->next;\
    free(aux);\
}\
*tail = NULL;\
}

DECLARE_DESTRUCTION_FUNCT(destroyListOne, NodeOne)
DECLARE_DESTRUCTION_FUNCT(destroyListTwo, NodeTwo)

这种类型从C ++复制模板。 带来了编译时类型检查的好处。