Cya*_*yan 11 c stack memory-management opaque-pointers
在设计C接口时,通常只允许.h用户程序需要知道的公共接口().
因此,例如,如果用户程序不需要知道它们,则结构的内部组件应该保持隐藏.这确实是一种很好的做法,因为结构的内容和行为将来可能会发生变化,而不会影响界面.
实现该目标的一个好方法是使用不完整的类型.
typedef struct foo opaqueType;
现在opaqueType可以构建仅使用指针的接口,而无需用户程序知道内部工作struct foo.
但有时,可能需要静态地(通常在堆栈上)分配此类结构,以解决性能和内存碎片问题.显然,上面的结构,opaqueType是不完整的,所以它的大小是未知的,所以它不能静态分配.
解决方法是分配"shell类型",例如:
typedef struct { int faketable[8]; } opaqueType;
上面的构造强制执行大小和对齐,但不会进一步描述结构真正包含的内容.因此它符合保持"不透明"类型的目标.
它主要起作用.但在一种情况下(GCC 4.4),编译器抱怨它打破了严格别名,并且它生成了错误的二进制文件.
现在,我已经阅读了大量关于严格混叠的内容,所以我想我现在明白这意味着什么.
问题是:有没有办法定义一个opaque类型,它仍然可以在堆栈上分配,而不会破坏严格的别名规则?
请注意,我已经尝试了这篇优秀文章中描述的union方法,但它仍然会生成相同的警告.
另请注意,visual,clang和gcc 4.6及更高版本不会抱怨并且可以正常使用此构造.
[编辑]信息补充:
根据测试,问题只发生在以下情况:
.c文件中的私有类型.如果他们是同一个联盟的一部分,那显然无关紧要.公共类型是否包含无关紧要char.最后,我的目标是C90.也许C99如果真的没有选择.
private您想要的是C 中C++ 访问控制的某种等效项。如您所知,不存在这样的等效项。你给出的方法大约就是我会做的。但是,我将使opaqueType实现该类型的内部组件变得不透明,因此我将被迫将其转换为内部组件中的真实类型。强制转换不应生成您提到的警告。
尽管使用起来很麻烦,但您可以定义一个接口,为不透明类型提供“堆栈分配”内存,而无需公开大小结构。这个想法是,实现代码负责堆栈分配,用户传入回调函数来获取指向分配类型的指针。
typedef struct opaqueType_raii_callback opqaueType_raii_callback;
struct opaqueType_raii_callback {
void (*func)(opqaueType_raii_callback *, opqaueType *);
};
extern void opaqueType_raii (opaqueType_raii_callback *);
extern void opaqueType_raii_v (opaqueType_raii_callback *, size_t);
void opaqueType_raii (opaqueType_raii_callback *cb) {
opaqueType_raii_v(cb, 1);
}
void opqaueType_raii_v (opaqueType_raii_callback *cb, size_t n) {
opaqueType x[n];
cb->func(cb, x);
}
Run Code Online (Sandbox Code Playgroud)
上面的定义看起来有点深奥,但这是我通常实现回调接口的方式。
struct foo_callback_data {
opaqueType_raii_callback cb;
int my_data;
/* other data ... */
};
void foo_callback_function (opaqueType_raii_callback *cb, opaqueType *x) {
struct foo_callback_data *data = (void *)cb;
/* use x ... */
}
void foo () {
struct foo_callback_data data;
data.cb.func = foo_callback_function;
opaqueType_raii(&data.cb);
}
Run Code Online (Sandbox Code Playgroud)