首页 > 解决方案 > 具有柔性阵列成员的不透明结构

问题描述

假设我在头文件中有一个结构声明,例如:

event.h

struct event_t;

在相应的 C 文件中,我想用 Linux 特定的struct inotify_event. 问题是struct inotify_event包含灵活的数组成员:

struct inotify_event {
    int      wd;      
    uint32_t mask;    
    uint32_t cookie;  
    uint32_t len;
    char     name[];   
};

根据6.7.2.1(p3) (强调我的):

结构或联合不应包含不完整或函数类型的成员(因此,结构不应包含自身的实例,但可能包含指向自身实例的指针),除非结构的最后一个成员具有超过一个命名成员可能有不完整的数组类型;这样的结构(以及任何可能递归地包含此类结构的成员 的联合)不应是结构的成员或数组的元素。

无法定义struct event_tas

struct event_t{
    struct inotify_event base; //Non-conforming
};

所以我可以转换struct event_t *struct inotify_event *. 由于6.7.2.1(p3)只关心结构,我看到的解决方案是将标签名称重新声明为

union event_t

然后稍后将其定义为单个元素联合。

union event_t{
    struct inotify_event event; //Conforming?
};

我发现标准对联合的唯一要求是联合的成员集必须是非空的6.2.5(p20)(强调我的):

联合类型描述了一组重叠的非空成员对象,每个对象都有一个可选的指定名称和可能的不同类型。

问题:通过隐藏某些特定数据结构的实现细节是一种符合/通用的方法union吗?

标签: clinuxstruct

解决方案


我会这样做:

事件.h

struct event_t;
event_t *create_event(void);
void free_event(event_t *ev);

事件.c

#include "event.h";

event_t *create_event(void)
{
    inotify_event *iev = ...;
    return (event_t *)iev;
}

void free_event(event_t *ev)
{
    inotify_event *iev = (inotify_event *)ev;
    // free the event
}

但是,如果您想在事件中存储其他数据,则:

事件.h

struct event_t;
event_t *create_event(void);
void free_event(event_t *ev);

事件.c

#include "event.h";

struct event_t
{
    inotify_event *iev;
    // additional data
};

event_t *create_event(void)
{
    inotify_event *iev = ...;
    event_t *ev = malloc(sizeof(event_t));
    ev.iev = iev;
    return ev;
}
void free_event(event_t *ev)
{
    inotify_event *iev = (inotify_event *)ev.iev;
    // free the event (iev) first
    free(ev);
}

如果您有多个需要隐藏的实现,event_t则:

enum event_type
{
    EVENT_TYPE_INOTIFY,
    EVENT_TYPE_INOTIFY2,
};
struct event_t
{
    event_type type;
    union {
       inotify_event *iev; // you use this when type == EVENT_TYPE_INOTIFY
       inotify_event2 *iev2; // you use this when type == EVENT_TYPE_INOTIFY2
    }
    // additional data
};

推荐阅读