到目前为止,我一直使用 void *
作为在 C 中封装私有(private)数据的方法。其想法是:用户不应该打扰内部,而只需请求公开的函数。
因此例如:
typedef void* myPrivateType;
myPrivateType createMPt(int someArg);
int doSomething(myPrivateType mpt, int someOtherArg);
void freeMpt(myPrivateType mpt);
这可以很好地隐藏 myPrivateType
的内部。然而,还有最后一个小问题:void*
非常宽松,编译器会默默地接受任何类型的指针,并且在类型不正确的情况下不会触发任何警告。
这看起来是一个小问题,但它只会增加用户不正确地使用界面并浪费大量时间来调试错误的可能性。
因此,我现在倾向于使用 incomplete types而不是 void*
,作为编译期间控制类型的更严格方法。
因此前面的示例如下:
typedef struct foo* myPrivateType;
myPrivateType createMPt(int someArg);
int doSomething(myPrivateType mpt, int someOtherArg);
void freeMpt(myPrivateType mpt);
如您所见,几乎没有任何变化,只有 typedef。它比之前的示例效果更好,就像现在一样,如果用户提供除“myPrivateType”之外的另一个指针,编译器会提示,并且错误将立即被捕获。
这是一个相当不错的选择。除此之外,在代码的“私有(private)部分”(.c
文件)中,我必须定义 struct foo
是什么。在某些情况下,当这些内容被明确且静态地定义时,它非常简单。
但有时,myPrivateType
的内容取决于运行时提供的某些变量,因此其大小可能会有所不同。这对于 C 结构体来说没有好处,因为它应该在编译时具有定义的大小。
作为一种解决方法,我可以这样 typedef myPrivateType :
typedef size_t* myPrivateType;
或
typedef size_t myPrivateType[]; // equivalent
这样可以稍后决定大小,作为 size_t
的倍数。但现在,myPrivateType
更加宽松,因为任何 size_t*
指针也符合要求。
我想知道是否有一种方法可以组合这两个属性,myPrivateType
非常严格,因此不可能与任何其他类型的指针混淆,但底层私有(private)数据保持了以下能力:在运行时选择其大小。
最佳答案
怎么样:
struct myPrivateType { void * private; };
使用方式基本上与使用原始 void 指针完全相同。您可以在 header 中公开整个结构,因为应用程序无论如何都无法对其包含的 void 指针执行任何操作。
这解决了 void * 隐式转换的问题,除了库函数中的 mpt->private 取消引用之外,不会引入任何麻烦。
编辑:如果您愿意,可以使用 typedef struct myPrivateType myPrivateType;
构造。
关于c - C 中可变大小结构的不完整类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30970054/