您所在位置:论坛首页 — C/C++语言 — C语言 —链表数据结构 本帖地址: http://bbs.pfan.cn/post-261414.html [复制地址] [搜索相关帖子] |
|||||
|
|
|||||||
|
|
作者:EVERGREEN19 专家分:110 ![]() ![]() |
1
楼
由于初学C 看了很久 不过终于看懂了 谢谢楼主 顶一个
此帖被评20分
|
|
作者:zhangwei123 专家分:2080 ![]() ![]() ![]() |
2
楼
谢谢分享,顶一下!
此帖被评20分
|
|
作者:fly_hyx 专家分:940 ![]() ![]() ![]() ![]() ![]() |
3
楼
学习了~ 谢谢分享
此帖被评20分
|
|
作者:windfoxe 专家分:70 ![]() ![]() |
4
楼
学习。。。。拜读大作啊,真是醍醐灌顶
![]() ☆★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★☆ 真诚为您有偿提供源代码服务,非诚勿扰。 (测绘专业、遥感应用和图像处理优先考虑) ☆★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★☆ 电子邮件: ereast@126.com QQ 号码 : 20271864 联系电话: 13770785571 15929337576 ☆★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★☆
此帖被评20分
|
|
作者:lin07860 专家分:370 ![]() ![]() |
5
楼
谢谢分享!
有几个地方看不明白希望大家能指点下,谢谢. #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) 上面这语句要怎么理解?(最好能讲细点,这东西我最头晕 )list_for_each(pos, head)与list_for_each_safe(pos, n, head)我怎么看是实现一样的效果,n在这里的操作似乎有点多此一举?
此帖被评20分
|
|
作者:bloodybg 专家分:1470 ![]() ![]() ![]() ![]() |
6
楼
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) 我们来一步一步的分析: 第一步:((type *)0)意思就是把0内存当作type指针来调用。 第二步:(unsigned long)(&((type *)0)->member)就是取0指针实例里一项的地址。 第三步:((char *)(ptr) 最ptr的地址。 第四步:拿第三步的地址 - 第二步的地址。最后的结果是什么呢?我们举个例子: 我们有一个结构: struct test { int a; int b; }; 现在创建一个这个结构的指针:test *ptr1; //假设它的内存际址是 addr1 那么我们像上面一样来调用: ((test*)0)内存中一开始的值当作(test*)指针来使用,那么现在就只用到0~sizeof(test)就是0~8长度的内存。 第二步:(unsigned long)(&((test*)0)->b) 的值是多少? 明显是 0 + sizeof(int) = 4 第三步:就是addr1 第四步:(char*)(&(ptr1)->b)就是取ptr1->b的地址,现在假设为addr2 因为一个结构在内存中是连续存放的,所以全用字节为单位来对每一个指针时,地址ptr1其它也是ptr1->a的地址,地址ptr1 加上4单位字节所指向的地址就是ptr1->b的地址。所以最后,我们就可以得到这个的等式 addr1 + 4 = addr2 这样就可以这样来理解上面的宏了:实例结构里某一项的地址,减去该项的偏移量,结果就是该实例的地址。 list_for_each(pos, head)与list_for_each_safe(pos, n, head)我怎么看是实现一样的效果,n在这里的操作似乎有点多此一举? list_for_each_safe是在删除所有结点时用的,我的例子没用到,不好意思。 我在这里用它提供的循环来删除所有结点。 void drop_list(list_head *head) { list_head *pos, *n; test_list *l = NULL; list_for_each_safe(pos, n, head) { l = list_entry(pos, test_list, head); free(l); } } 这里,如果你只是用list_for_each来删除的话,free掉了l,那么pos的值就不确定了,再pos = pos->next就是出错。这里的删除所有的结点时有一个好处就是不用操作list_del。 我也是在学习,有说的不对的地方,望高手指点改正,谢谢!
![]() 全部从零开始!!!!!! |
|
作者:bloodybg 专家分:1470 ![]() ![]() ![]() ![]() |
7
楼
C语言里有一个叫offsetof的宏
它的实现跟list_entry差不多 你可以去网上找一下它的说明 对list_entry有一定的帮助
![]() 全部从零开始!!!!!! |
|
作者:nyra 专家分:4650 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
8
楼
a = (type*)0 由0构造一个结构指针.
offset = &(a)->member, member的地址,注意a = 0所以member的地址其实也是member在结构体内的偏移. p = (char *)(ptr)-(unsigned long)(offset) ptr减去它自己在结构体内的偏移,即是结构体的首地址. for_each中 pos = pos->next.问题是如果pos->next被修改了,比如pos从链表中删除了. pos = pos->next还能得到正确的结果吗? 用n保存pos->next即可达成这一目的.
此帖被评20分
|
|
作者:lin07860 专家分:370 ![]() ![]() |
9
楼
谢谢楼上二位,,学习了
此帖尚未评分
|
|
作者:jxj777 专家分:2630 ![]() ![]() ![]() ![]() ![]() ![]() |
10
楼
学习了,谢谢...
此帖被评20分
|
|
作者:hanhaixingyun777 专家分:50 ![]() ![]() |
11
楼
楼主真大方.的确值得学习
此帖被评20分
|
|
作者:dvdaxia 专家分:20 ![]() ![]() |
12
楼
看了很久,终于明白了!
此帖被评20分
|
|
作者:vanehu 专家分:0 ![]() ![]() |
13
楼
我也正在学习数据结构,谢谢楼主分享
此帖尚未评分
|
|
作者:andyshuai 专家分:10 ![]() ![]() |
14
楼
多谢分享!!!
此帖尚未评分
|
|
作者:地球人民 专家分:70 ![]() ![]() |
15
楼
好!顶一下!
此帖尚未评分
|
|