在设计 C 接口时,通常只让.h
用户程序知道的内容进入公共接口 ( )。
因此,例如,如果用户程序不需要知道结构的内部组件,则它们应该保持隐藏。这确实是一种很好的做法,因为结构的内容和行为将来可能会发生变化,而不会影响界面。
实现该目标的一个好方法是使用不完整类型。
typedef struct foo opaqueType;
现在可以构建一个只使用指针的接口opaqueType
,而用户程序不需要知道struct foo
.
但有时,可能需要静态分配此类结构,通常在堆栈上,以解决性能和内存碎片问题。显然,上面的构造,opaqueType
是不完整的,所以它的大小是未知的,所以它不能被静态分配。
一种解决方法是分配“外壳类型”,例如:
typedef struct { int faketable[8]; } opaqueType;
上面的构造强制了大小和对齐,但没有进一步描述结构真正包含的内容。所以它符合保持类型“不透明”的目标。
它主要工作。但在一种情况下(GCC 4.4),编译器抱怨它破坏了严格的别名,并生成了错误的二进制文件。
现在,我已经阅读了大量关于严格别名的内容,所以我想我现在明白它的含义了。
问题是:有没有办法定义一个不透明的类型,它仍然可以在堆栈上分配,并且不违反严格的别名规则?
请注意,我已经尝试过这篇优秀文章中描述的联合方法,但它仍然会产生相同的警告。
另请注意,视觉、clang 和 gcc 4.6 及更高版本不会抱怨并且可以正常使用此构造。
[编辑]信息补充:
根据测试,该问题仅在以下情况下发生:
- 私有和公共类型不同。我在
.c
文件中将公共类型转换为私有。他们是否属于同一个工会显然并不重要。公共类型是否包含char
. - 如果私有类型的所有操作都只是读取,那没有问题。只有写入会导致问题。
- 我还怀疑只有自动内联的函数才会遇到麻烦。
- 问题仅发生在 gcc 4.4 的 -O3 设置上。-O2 很好。
最后,我的目标是C90。如果真的别无选择,也许是C99。