最近看 wpa_supplicant 的代码,发现有许多的结构体都相互嵌套
什么情况下我们会选择这种相互嵌套的结构?
例如下面的 wpa_supplicant 和 wpa_global
exp:
struct wpa_supplicant {
struct wpa_global *global;
struct wpa_radio *radio; /* shared radio context */
struct dl_list radio_list; /* list head: struct wpa_radio::ifaces */
struct wpa_supplicant *parent;
struct wpa_supplicant *p2pdev;
struct wpa_supplicant *next;
struct l2_packet_data *l2;
struct l2_packet_data *l2_br;
unsigned char own_addr[ETH_ALEN];
unsigned char perm_addr[ETH_ALEN];
char ifname[100];
...
struct wpa_global {
struct wpa_supplicant *ifaces;
struct wpa_params params;
struct ctrl_iface_global_priv *ctrl_iface;
struct wpas_dbus_priv *dbus;
struct wpas_binder_priv *binder;
void **drv_priv;
size_t drv_count;
struct os_time suspend_time;
struct p2p_data *p2p;
struct wpa_supplicant *p2p_init_wpa_s;
struct wpa_supplicant *p2p_group_formation;
struct wpa_supplicant *p2p_invite_group;
...
1
wizardoz 2019-01-10 13:36:14 +08:00
这个不叫嵌套好吧,顶多算是一种关联。
|
2
wizardoz 2019-01-10 13:37:42 +08:00 2
就好比双向链表,a 的 next 指向 b,b 的 prev 指向 a。你不能说它是相互嵌套啊
|
3
jagger2048 2019-01-10 13:50:01 +08:00 2
相互嵌套 谈不上,用个结构体封装其他结构体指针,可以比较方便地管理资源,如果是 C++可以用类的某些特性(派生继承多态)来封装
|
4
aijam 2019-01-10 14:13:03 +08:00
爹认识儿子,儿子也要认识爹。
|
5
zn 2019-01-10 14:19:04 +08:00
这个叫互相引用,不叫互相嵌套。
|
6
GeruzoniAnsasu 2019-01-10 14:21:15 +08:00 1
这是个每个节点都带有指向根节点指针的树结构
|
7
wutiantong 2019-01-10 14:56:55 +08:00
99%的 C 语言项目都能看到这种“相互嵌套”,题主一定是没用 C 语言做过工程实践。
|
8
dazhangpan 2019-01-10 16:18:11 +08:00
有点就是互相都知道地址,去谁家串个门都方便
|
9
liuxey 2019-01-10 16:22:49 +08:00
互相引用这种事情别说 C,Java 里也很常见嘛,还记得一对多和多对多吗
|
10
reus 2019-01-10 16:25:03 +08:00
那是指针,存的是指针,没有嵌套
真的嵌套的话,是编译不过的,因为结构体大小是无限大,没法编译 |
11
flyingghost 2019-01-10 17:26:25 +08:00
相互嵌套。。。吓我一大跳,申请一个实例直接就爆内存了啊喂!
只是互相关联,互相存一个指针而已。莫慌,莫慌。 |
12
FrankHB 2019-01-10 20:33:11 +08:00 1
看起来是作者水平比较屎,因为无知或盲信 Linux Kernel Coding Style 5)之类的反智胡扯,不知道用显式类型体现更明确的目的(考虑到下面的 magic,前者跑不掉)。换 C 艹可能就被打死了。
真正互相引用的像链表的 prev/next 的情况理应是非常少的,并且基本可以且往往应该排除出业务代码。 然后看了下代码(主要是 wpa_supplicant_deinit_iface ),果然是属于混用所有权和链表访问的需要被打死的情况。在我这边 review 避免被打死的标准套路起手( C 艹版本)是 wpa_supplicant *ifaces 改成 pmr::list<wpa_supplicant> ifaces,struct wpa_global *global 改成 observer_ptr<wpa_global>。C 嘛要考虑的细节麻烦多了(……比如避免_t 踩到 POSIX reserve name ),懒得示范了。 |
13
FrankHB 2019-01-10 20:41:29 +08:00
贴漏了,observer_ptr<wpa_global>后补 global。另外看起来是内部用的,不管 ABI compat 直接改 pmr::forward_list 好了,更接近原逻辑。
@jagger2048 知道是 C 代码就别拿 C 艹的习惯说大话了,看看实际代码就知道不符合你这里说的任何一种情况(尽管看的确实是“资源管理”有点关系的代码)。 |
14
cwx391497 OP @GeruzoniAnsasu 谢谢,我数据结构就了解到链表那里,会去补一下相关知识
|