因此,例如,如果用户程序不需要知道结构的内部组件应该保持隐藏.这是一个很好的做法,因为结构的内容和行为在将来会发生变化,而不影响界面.
实现这一目标的一个很好的方法是使用不完整的类型.
typedef struct foo opaqueType;
现在可以构建一个仅使用opaqueType指针的界面,而不需要用户程序来了解struct foo的内部工作.
但是有时,可能需要静态地分配这样的结构,通常在堆栈上,用于性能和内存分片问题.显然,在上面的构造中,opaqueType是不完整的,所以它的大小是未知的,所以它不能被静态分配.
一个工作是分配一个“shell类型”,如:
typedef struct {int faketable [8]; } opaqueType;
以上构造强制大小和对齐,但不会更深入地描述结构真正包含什么.所以它符合保持类型“不透明”的目标.
它主要工作.但是在一种情况(GCC 4.4)中,编译器抱怨说它破坏了严格的别名,并且生成了错误的二进制文件.
现在,我已经读了很多有关严格混叠的事情,所以我想我现在明白了什么意思.
问题是:有没有办法定义一个不透明的类型,可以在堆栈上分配,而不会破坏严格的别名规则?
请注意,我尝试了union method described in this excellent article,但仍然产生相同的警告.
还要注意,视觉,cl ang和gcc 4.6及更高版本不要抱怨并且工作正常.
信息补充:
根据测试,问题只发生在以下情况:
>私人和公共类型不同.我将公共类型转换为.c文件中的私有类型.如果他们是同一个联盟的一部分,这并不重要.公共类型包含char也没关系.
>如果私有类型的所有操作都只是读取操作,则没有问题.只有写入会导致问题.
>我也怀疑只有自动内嵌的功能才会陷入困境.
>问题只发生在gcc 4.4在-O3设置. -O2很好
最后,我的目标是C90.也许C99如果真的没有选择.
解决方法
沿着以下方向的东西:
#include <stdint.h> struct opaque { union { max_align_t a; char b[32]; // or whatever size you need. } u; };
如果要支持没有max_align_t的编译器,或者如果您知道实际类型的对齐要求,则可以使用任何其他类型的联合成员.
更新:如果您正在定位C11,那么您也可以使用alignas():
#include <stdint.h> #include <stdalign.h> struct opaque { alignas(max_align_t) char b[32]; };
当然,您可以用您认为合适的任何类型替换max_align_t.甚至一个整数.
更新#2:
那么在图书馆中使用这种类型的东西就是这样的:
void public_function(struct opaque *po) { struct private *pp = (struct private *)po->b; //use pp->... }
这样,由于您是对char指针进行打字,您不会违反严格的别名规则.