如何在不使用 Malloc 的情况下使 typedef 尽可能私有?
How to make a typedef as private as possible without using Malloc?
我正在寻找一种方法来制作只能从一组特定的函数调用(setBit(bit_typ *const t),getBit(bit_typ *常量 t))。我正在寻找一种不使用 malloc 的方法来做到这一点,有人有什么想法吗?
EDIT:// 这个问题与 this one 不同,因为它正在寻找接近 "private" 结构的方法,而另一个问题(TL;DR 有办法定义一个不透明类型,它仍然可以在堆栈上分配,并且不会违反严格的别名规则?)寻找与我的问题的一种可能解决方案相关的问题的解决方案。
一种方法是公开不透明类型的总 大小 并使用将不透明类型的对象声明为 unsigned char [N]
缓冲区。例如,假设您有一些类型 OpaqueType
,您希望向用户隐藏其内部结构。
在头文件中(暴露给用户)你这样做
typedef unsigned char OpaqueType[16];
其中 16
是您要隐藏的类型的确切字节大小。在头文件中,您根据该类型编写整个接口,例如
void set_data(OpaqueType *dst, int data);
在实现文件中声明实际类型
typedef struct OpaqueTypeImpl
{
int data1;
double data2;
} OpaqueTypeImpl;
实现功能如下
void set_data(OpaqueType *dst, int data)
{
OpaqueTypeImpl *actual_dst = (OpaqueTypeImpl *) dst;
actual_dst->data1 = data;
}
您还可以添加静态断言,以确保 sizeof(OpaqueType)
与 sizeof(OpaqueTypeImpl)
相同。
当然,正如下面的评论中所指出的,必须采取额外的步骤来确保此类对象的正确对齐,例如 C11 中的 _Alignas
或 [= 中的一些基于联合的技术46=] C.
这样你就给了用户声明 OpaqueType
的非动态对象的机会,即你不会强迫用户调用你的函数,在内部 malloc
这样的对象。同时,您不会向用户公开您类型的内部结构的任何信息(除了其总大小和对齐要求)。
另请注意,以这种方式声明的 OpaqueType
是一个数组,这意味着它不可复制(除非您使用 memcpy
)。如果您想主动防止不受限制的用户级复制,那可能是一件好事。但是如果你想启用复制,你可以将数组包装成一个结构。
这种方法不是非常优雅,但是当您希望让您的类型的对象自由由用户定义时,这可能是隐藏实现的唯一方法。
我正在寻找一种方法来制作只能从一组特定的函数调用(setBit(bit_typ *const t),getBit(bit_typ *常量 t))。我正在寻找一种不使用 malloc 的方法来做到这一点,有人有什么想法吗?
EDIT:// 这个问题与 this one 不同,因为它正在寻找接近 "private" 结构的方法,而另一个问题(TL;DR 有办法定义一个不透明类型,它仍然可以在堆栈上分配,并且不会违反严格的别名规则?)寻找与我的问题的一种可能解决方案相关的问题的解决方案。
一种方法是公开不透明类型的总 大小 并使用将不透明类型的对象声明为 unsigned char [N]
缓冲区。例如,假设您有一些类型 OpaqueType
,您希望向用户隐藏其内部结构。
在头文件中(暴露给用户)你这样做
typedef unsigned char OpaqueType[16];
其中 16
是您要隐藏的类型的确切字节大小。在头文件中,您根据该类型编写整个接口,例如
void set_data(OpaqueType *dst, int data);
在实现文件中声明实际类型
typedef struct OpaqueTypeImpl
{
int data1;
double data2;
} OpaqueTypeImpl;
实现功能如下
void set_data(OpaqueType *dst, int data)
{
OpaqueTypeImpl *actual_dst = (OpaqueTypeImpl *) dst;
actual_dst->data1 = data;
}
您还可以添加静态断言,以确保 sizeof(OpaqueType)
与 sizeof(OpaqueTypeImpl)
相同。
当然,正如下面的评论中所指出的,必须采取额外的步骤来确保此类对象的正确对齐,例如 C11 中的 _Alignas
或 [= 中的一些基于联合的技术46=] C.
这样你就给了用户声明 OpaqueType
的非动态对象的机会,即你不会强迫用户调用你的函数,在内部 malloc
这样的对象。同时,您不会向用户公开您类型的内部结构的任何信息(除了其总大小和对齐要求)。
另请注意,以这种方式声明的 OpaqueType
是一个数组,这意味着它不可复制(除非您使用 memcpy
)。如果您想主动防止不受限制的用户级复制,那可能是一件好事。但是如果你想启用复制,你可以将数组包装成一个结构。
这种方法不是非常优雅,但是当您希望让您的类型的对象自由由用户定义时,这可能是隐藏实现的唯一方法。