c/c++语言开发共享C通用链表

我有一个通用链接列表,其中包含void *类型的数据我试图用类型struct employee填充我的列表,最终我想破坏对象struct employee。

考虑这个通用的链表头文件(我用char *类型测试过它):

struct accListNode //the nodes of a linked-list for any data type { void *data; //generic pointer to any data type struct accListNode *next; //the next node in the list }; struct accList //a linked-list consisting of accListNodes { struct accListNode *head; struct accListNode *tail; int size; }; void accList_allocate(struct accList *theList); //allocate the accList and set to NULL void appendToEnd(void *data, struct accList *theList); //append data to the end of the accList void removeData(void *data, struct accList *theList); //removes data from accList -------------------------------------------------------------------------------------- 

考虑员工结构

 struct employee { char name[20]; float wageRate; } 

现在考虑将从main()调用的示例测试用例:

  void test2() { struct accList secondList; struct employee *emp = Malloc(sizeof(struct employee)); emp->name = "Dan"; emp->wageRate =.5; struct employee *emp2 = Malloc(sizeof(struct employee)); emp2->name = "Stan"; emp2->wageRate = .3; accList_allocate(&secondList); appendToEnd(emp, &secondList); appendToEnd(emp2, &secondList); printf("Employee: %sn", ((struct employee*)secondList.head->data)->name); //cast to type struct employee printf("Employee2: %sn", ((struct employee*)secondList.tail->data)->name); } 

为什么我在下面发布的答案解决了我的问题? 我相信它与指针和内存分配有关。 我使用的函数Malloc()是一个自定义malloc,它检查返回的NULL。

这是我的整个通用链表实现的链接: https : //codereview.stackexchange.com/questions/13007/c-linked-list-implementation

    问题是这个accList_allocate()和你使用它。

     struct accList secondList; accList_allocate(&secondList); 

    在原始test2()中,secondList是堆栈上的内存。 &secondList是指向该内存的指针。 当你调用accList_allocate()时,指针的副本将指向堆栈内存。 然后,Malloc()返回一块内存并将其分配给指针的副本,而不是原始的secondList。

    退出后,secondList仍指向堆栈上未初始化的内存,因此对appendToEnd()的调用失败。

    除了secondList恰好没有垃圾之外,答案也是如此。 可能是偶然的,可能是编译器的设计。 无论哪种方式,它都不是你应该依赖的东西。

    或者:

     struct accList *secondList = NULL; accList_allocate(&secondList); 

    并更改accList_allocate()

     accList_allocate(struct accList **theList) { *theList = Malloc(sizeof(struct accList)); (*theList)->head = NULL; (*theList)->tail = NULL; (*theList)->size = 0; } 

    要么

     struct accList secondList; accList_initialise(secondList); 

    将accList_allocate()更改为accList_initialise()因为它没有分配

     accList_initialise(struct accList *theList) { theList->head = NULL; theList->tail = NULL; theList->size = 0; } 

    我认为你的问题是这样的:

    main分配它时它起作用的原因是你的C编译器可能在程序启动时将堆栈归零。 当main在堆栈上分配一个变量时,该分配是持久的(直到程序结束),所以当你在main分配它时, secondList实际上并且意外地正确初始化了。

    您当前的accList_allocate实际上并未初始化传入的指针,其余代码将永远不会看到它使用Malloc分配的指针。 为了解决您的问题,我将创建一个新函数: accList_initialize其唯一的工作是初始化列表:

     void accList_initialize(struct accList* theList) { // NO malloc theList->head = NULL; theList->tail = NULL; theList->size = 0; } 

    在原始test2函数中使用this而不是accList_allocate 。 如果你真的想在堆上分配列表,那么你应该这样做(而不是将它与在堆栈上分配的结构混合)。 让accList_allocate 返回指向已分配结构的指针:

     struct accList* accList_allocate(void) { struct accList* theList = Malloc( sizeof(struct accList) ); accList_initialize(theList); return theList; } 

    当我在main()中放置secondList的声明和分配,并将其余部分放在一个函数中时,它可以工作:

     int main(int argc, char *argv[]) { struct accList secondList; accList_allocate(&secondList); test2(&secondList); return 0; } void test2(struct accList *secondList) { struct employee *emp = Malloc(sizeof(struct employee)); struct employee *emp2 = Malloc(sizeof(struct employee)); strcpy(emp->name, "Dan"); emp->wageRate = .5; appendToEnd(emp, secondList); strcpy(emp2->name, "Stan"); emp2->wageRate = .3; appendToEnd(emp2, secondList); printf("Employee: %sn", ((struct employee*)secondList->head->data)->name); //cast to type struct employee printf("Employee2: %sn", ((struct employee*)secondList->tail->data)->name); removeData(emp, secondList); printf("Head: %sn", ((struct employee*)secondList->head->data)->name); } struct employee { char name[20]; float wageRate; } 

    这是整个实现的链接。

    我觉得这与指针和分配有关。 有人可以向我解释那部分吗? 将问题中的代码与上面的代码进行比较。

    谢谢!

    根据原始代码我在这里看到的两件事是错的,在上面的问题中,

    您所看到的是未定义的行为,并且由此产生的是总线错误消息,因为您正在为变量分配字符串文字,实际上您应该使用strcpy函数,因此您已经按照原样编辑了原始代码。 。将来要记住的事情:)

    使用Malloc这个词会引起混淆,特别是在同行评审中,评论者会有一个大脑屁并说“哇,这是什么,不应该是malloc吗?” 并很可能提高它。 (基本上,不要调用具有与C标准库函数类似的声音名称的自定义函数)

    你没有检查NULL ,如果你的加强版的Malloc失败了那么emp将会是NULL ! 总是检查一下无论多么微不足道或你的想法是“啊,这个平台上有大量的内存,4GB RAM没问题,不会费心去检查NULL”

    看看其他地方发布的这个问题来解释什么是总线错误。

    编辑:使用链表结构,如何调用函数中的参数对于理解它是至关重要的。 注意的用法,意思是获取指向链表结构的变量的地址 ,并通过引用传递它 ,而不是传递作为变量副本的值。 同样的规则同样适用于指针的使用:)

    你在问题的第一个代码中有一些参数稍微&secondList ,如果你在参数列表中使用双指针然后是,使用&secondList就可以了。

    这可能取决于您的员工结构的设计方式,但您应该注意到这一点

     strcpy(emp->name, "Dan"); 

     emp->name = "Dan"; 

    function不同。 特别是,后者可能是总线错误的来源,因为您通常无法以这种方式写入字符串文字。 特别是如果您的代码有类似的东西

    name =“NONE”

    等等。

    编辑:好的,所以对于员工结构的设计,问题是:

    您无法分配给arrays。 C标准包括可修改的左值列表,而arrays不是其中之一。

     char name[20]; name = "JAMES" //illegal 

    strcpy很好 – 它只是去名称[0]取消引用的内存地址,并将“JAMES 0”复制到那里的内存中,一次一个字节。

    需要了解更多c/c++开发分享C通用链表,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!

      以上就是c/c++开发分享C通用链表相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/979459.html

      (0)
      上一篇 2021年12月12日
      下一篇 2021年12月12日

      精彩推荐