C中可堆栈的不透明类型

在设计C接口时,通常仅将用户程序中需要知道的公共接口(.h).

因此,例如,如果用户程序不需要知道结构的内部组件应该保持隐藏.这是一个很好的做法,因为结构的内容和行为在将来会发生变化,而不影响界面.

实现这一目标的一个很好的方法是使用不完整的类型.

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如果真的没有选择.

解决方法

您可以强制使用max_align_t进行对齐,您可以使用char数组来避免严格的别名问题,因为char被明确允许别名为任何其他类型.

沿着以下方向的东西:

#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指针进行打字,您不会违反严格的别名规则.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...