Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对于不同的列表结构,是否可以用C编写一个通用遍历函数,只要它们包含;“下一步”;领域_C_List_Casting_Traversal - Fatal编程技术网

对于不同的列表结构,是否可以用C编写一个通用遍历函数,只要它们包含;“下一步”;领域

对于不同的列表结构,是否可以用C编写一个通用遍历函数,只要它们包含;“下一步”;领域,c,list,casting,traversal,C,List,Casting,Traversal,第一次问问题,但我确实环顾了谷歌和stackoverflow,看看是否有人问过类似的问题。比如,OP问了一些类似的问题。但它更复杂 我想知道,如果您知道不同类型的结构总是有一个“next”字段,那么是否可以在C中为遍历列表的列表结构创建一个通用函数 例如,给定以下两种列表类型结构: typedef结构\u列表1{ int值; 列表1*下一步; }清单1; 类型定义结构列表2{ int值; 字符*字符串; 列表2*下一步; }清单2; 是否可以创建一个通用的void freeList((void

第一次问问题,但我确实环顾了谷歌和stackoverflow,看看是否有人问过类似的问题。比如,OP问了一些类似的问题。但它更复杂

我想知道,如果您知道不同类型的结构总是有一个“next”字段,那么是否可以在C中为遍历列表的列表结构创建一个通用函数

例如,给定以下两种列表类型结构:

typedef结构\u列表1{
int值;
列表1*下一步;
}清单1;
类型定义结构列表2{
int值;
字符*字符串;
列表2*下一步;
}清单2;
是否可以创建一个通用的
void freeList((void*)list)
函数或类似下面的东西?我知道为每个单独的列表分别编写两个自由函数是一件简单的事情

void自由列表((void*)列表){
//包含此项是因为结构的大小不同
//所以我认为,为了正确地取消对字段的引用,可以对其进行强制转换。
if(sizeof*list==sizeof list1)
*列表=(列表1)列表;
else if(sizeof*list==sizeof list2)
*列表=(列表2)列表;
如果(!list)返回;
否则{
免费(列表->下一步);
免费(名单);
}
}

到目前为止,由于gcc会抱怨取消对
void*
指针的引用,我对上面显示的代码进行的实验并不顺利。

创建异构列表可以通过使用标记的联合,或者只使用标记和强制转换来实现:

struct list_item {
    struct list_item *next;
    enum datatype type;
    void *contents;
};

然后,在遍历列表时,只需在使用元素内容之前验证
type
中存储的类型


此支票:

if (sizeof *list == sizeof list1)
    *list = (list1) list;
else if (sizeof *list == sizeof list2)
    *list = (list2) list;

不起作用,因为
sizeof
是一个静态构造:其值在编译时定义。您只需要询问void的大小,如果您确保下一个指针是结构的第一个成员,那么这是可能的

typedef struct list1 {
    // next pointer must be first
    struct list1 *next;
    int value;
} list1;

typedef struct list2 {
    // next pointer must be first
    struct list2 *next;
    int value;
    char *string;
} list2;

void freeList(void *list) {
    if (list) {
        freeList(*(void**)list);
        free(list);
    }
}
如果您知道不同类型的结构总是有一个“next”字段,那么是否可以在C中为遍历列表的列表结构创建一个通用函数

是的,如前所述;您必须注意,每个结构都以“next”字段开头;因此,您的帖子中的两个结构应该按如下方式重新排序:

typedef struct _list1 {
    list1 *next;
    int value;
} list1;

typedef struct _list2 {
    list2 *next;
    int value;
    char *string;
} list2;
它不是干净的代码,因为编译器可以重新排序(并填充)结构的字段,但一般来说它应该可以工作

是否可以创建一个通用的void freeList((void)*list)函数或类似于

如果您的结构引用malloced内存,这是可能的;或者他们会这样做,但是以一种统一的(并且已知的)方式(注意第一种情况是最后一种情况的子情况)

如果结构包含指向必须释放的内存的指针,事实上,在释放结构时,freeList()函数还应该释放引用的内存。我想到了一些解决方案:

1-如果所有不同的结构包含相同的“指针”布局,例程可以以统一的方式释放这些指针,提前知道该做什么。在这种情况下,还可以使用并非所有结构都使用的指针字段,而只是部分结构使用的指针字段

2-结构的每个实例都可能包含一些描述指针布局的帮助器字段。例如,就在“next”字段之后,另一个“mempntcnt”字段可以告诉“next”字段后面有多少指针(要释放)。或者,这个“mempntcnt”可以作为参数传递给freeList()

3-此问题可以通过完全分离的机制进行管理,不在freeList()的范围内。这在很大程度上取决于最终的用法:我的意思是,对于给定的(某种)链表,首先调用一个例程释放列表本身引用的所有内存,然后通过调用common freeList()释放列表。毕竟,如果需要不同的结构,那么对它们使用不同的例程


我希望我已经足够清楚了…

linux内核有一个。其他图书馆也提供类似的服务。这就是你所想的吗?@kaylum说实话,在阅读了实现之后,我仍然不能完全理解它,所以我恐怕不能真正说出来。虽然这很有趣,但我希望在更透彻地阅读之后理解它。这至少有两个问题:它打破了严格的别名,并且不能保证
sizeof(void**)==sizeof(struct list1*)
(虽然我不知道有什么通用的,但也有一些平台不支持它)。不允许对字段进行重新排序。@linuxfan正如@Aprogrammer提到的,我之所以想问这个问题,是因为我无法修改结构。然而,正如您和@Kerndog73所指出的,我认为这将是理想的解决方案。我没有考虑对字段进行重新排序,因为我总是假设
下一个
指针通常在末尾附近。我是否应该意识到将下一个指针放在第一位可能会产生什么问题?这就是为什么它必须是第一个字段的原因,它与大/小尾端以及它如何存储在内存中有关吗?@WhonderWy对我来说,将
下一个
字段放在第一位只是将它放在记录中已知偏移量的可能方法之一。不,这与endian问题无关。关于字段的重新排序,是否不允许符合条件的编译器执行此操作?好的,但我见过不兼容的编译器,所以我更喜欢含糊和保守。谢谢你这么快回答!我不知道这一点有多大。如果我是创建列表结构的人,拥有一个联合或枚举会很好,但我考虑的不是修改结构的联合或枚举,而是rat
typedef struct _list1 {
    list1 *next;
    int value;
} list1;

typedef struct _list2 {
    list2 *next;
    int value;
    char *string;
} list2;