设计 C 接口时,常见的做法是只在公共接口(
实现该目标的好方法是使用不完整类型。现在我们可以建立一个仅使用指向
但有时,可能需要静态分配这样的结构,通常在堆栈上进行操作以提高性能和内存碎片问题。显然,通过上述结构,
解决方法是分配“shell type”,例如:
现在,我已经阅读了很多关于严格别名的东西,所以我想我现在理解了它的含义。问题是:是否有一种方法可以定义一个不透明类型,但仍然可以在堆栈上分配,而不会违反严格别名规则?
请注意,我尝试过本文中描述的联合方法,但它仍会生成相同的警告。请注意,Visual、Clang 和 GCC 4.6 及更高版本都没有抱怨并可以正常工作。
.h
)中暴露用户程序需要知道的内容。因此,例如,如果用户程序不需要知道结构的内部组件,则应将其保留隐藏。这确实是一种良好的实践方法,因为结构的内容和行为可能会在未来发生变化,而不影响接口。实现该目标的好方法是使用不完整类型。现在我们可以建立一个仅使用指向
opaqueType
的指针的接口,而无需用户程序了解 struct foo
的内部工作。但有时,可能需要静态分配这样的结构,通常在堆栈上进行操作以提高性能和内存碎片问题。显然,通过上述结构,
opaqueType
是不完整的,因此其大小未知,因此无法进行静态分配。解决方法是分配“shell type”,例如:
typedef struct { int faketable[8]; } opaqueType;
以上结构强制设定了大小和对齐方式,但并没有更深入地描述结构的真正内容。因此,它符合使类型“不透明”的目标。它基本上是有效的,但在某些情况下(例如 GCC 4.4),编译器会抱怨它违反了严格别名规则,从而生成有缺陷的二进制文件。现在,我已经阅读了很多关于严格别名的东西,所以我想我现在理解了它的含义。问题是:是否有一种方法可以定义一个不透明类型,但仍然可以在堆栈上分配,而不会违反严格别名规则?
请注意,我尝试过本文中描述的联合方法,但它仍会生成相同的警告。请注意,Visual、Clang 和 GCC 4.6 及更高版本都没有抱怨并可以正常工作。
根据测试,问题只在以下情况下发生:
- 私有和公共类型不同。我在.c文件中将公共类型强制转换为私有类型。如果它们是同一个联合的一部分,显然无关紧要。如果公共类型包含
char
也无妨。 - 如果对私有类型的所有操作仅为读取,则没有问题。只有写入才会导致问题。
- 我还怀疑仅自动内联的函数会遇到麻烦。
- 该问题仅在-gcc 4.4设置为-O3时发生。 -O2则没有问题。
最后,我的目标是C90。如果确实没有选择,则使用C99。