V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cwx391497
V2EX  ›  C

C 语言中结构体相互嵌套有什么优点吗

  •  
  •   cwx391497 · 2019-01-10 13:22:19 +08:00 · 4506 次点击
    这是一个创建于 2128 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近看 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;
    ...
    
    14 条回复    2019-01-11 08:13:12 +08:00
    wizardoz
        1
    wizardoz  
       2019-01-10 13:36:14 +08:00
    这个不叫嵌套好吧,顶多算是一种关联。
    wizardoz
        2
    wizardoz  
       2019-01-10 13:37:42 +08:00   ❤️ 2
    就好比双向链表,a 的 next 指向 b,b 的 prev 指向 a。你不能说它是相互嵌套啊
    jagger2048
        3
    jagger2048  
       2019-01-10 13:50:01 +08:00   ❤️ 2
    相互嵌套 谈不上,用个结构体封装其他结构体指针,可以比较方便地管理资源,如果是 C++可以用类的某些特性(派生继承多态)来封装
    aijam
        4
    aijam  
       2019-01-10 14:13:03 +08:00
    爹认识儿子,儿子也要认识爹。
    zn
        5
    zn  
       2019-01-10 14:19:04 +08:00
    这个叫互相引用,不叫互相嵌套。
    GeruzoniAnsasu
        6
    GeruzoniAnsasu  
       2019-01-10 14:21:15 +08:00   ❤️ 1
    这是个每个节点都带有指向根节点指针的树结构
    wutiantong
        7
    wutiantong  
       2019-01-10 14:56:55 +08:00
    99%的 C 语言项目都能看到这种“相互嵌套”,题主一定是没用 C 语言做过工程实践。
    dazhangpan
        8
    dazhangpan  
       2019-01-10 16:18:11 +08:00
    有点就是互相都知道地址,去谁家串个门都方便
    liuxey
        9
    liuxey  
       2019-01-10 16:22:49 +08:00
    互相引用这种事情别说 C,Java 里也很常见嘛,还记得一对多和多对多吗
    reus
        10
    reus  
       2019-01-10 16:25:03 +08:00
    那是指针,存的是指针,没有嵌套

    真的嵌套的话,是编译不过的,因为结构体大小是无限大,没法编译
    flyingghost
        11
    flyingghost  
       2019-01-10 17:26:25 +08:00
    相互嵌套。。。吓我一大跳,申请一个实例直接就爆内存了啊喂!

    只是互相关联,互相存一个指针而已。莫慌,莫慌。
    FrankHB
        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 ),懒得示范了。
    FrankHB
        13
    FrankHB  
       2019-01-10 20:41:29 +08:00
    贴漏了,observer_ptr<wpa_global>后补 global。另外看起来是内部用的,不管 ABI compat 直接改 pmr::forward_list 好了,更接近原逻辑。

    @jagger2048 知道是 C 代码就别拿 C 艹的习惯说大话了,看看实际代码就知道不符合你这里说的任何一种情况(尽管看的确实是“资源管理”有点关系的代码)。
    cwx391497
        14
    cwx391497  
    OP
       2019-01-11 08:13:12 +08:00
    @GeruzoniAnsasu 谢谢,我数据结构就了解到链表那里,会去补一下相关知识
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3909 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 04:13 · PVG 12:13 · LAX 20:13 · JFK 23:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.