微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

原文地址:https://www.jb51.cc/c/114244.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐