什么是C中的不透明指针?


78

我可以知道C中不透明指针概念背后的用法和逻辑吗?



25
我对Wiki页面一无所知。
Renjith G

2
嗯 这个关于C的问题已经复制到一个带标签的C ++中。那不理想。有足够的共性,这不是一个大问题,但C ++有不可用在C选项和功能
乔纳森·莱弗勒

Answers:


124

不透明指针是一种不透露基础数据细节的指针(根据字典定义:opaque:形容词;无法透视;不透明)。

例如,您可以在头文件中声明(这来自我的一些实际代码):

它声明的类型pmpi是指向不透明结构 的指针struct pmpi_s,因此您声明的任何内容都pmpi将是不透明的指针。

该声明的用户可以自由编写如下代码:

不知道结构的实际“定义”。

然后,在了解定义的代码(即提供pmpi处理功能的代码)中,可以“定义”结构:

并轻松访问它的各个字段,而标头文件的用户无法执行此操作。

有关不透明指针的更多信息,请参见Wikipedia页面

它的主要用途是向您的库用户隐藏实现细节。封装(尽管C ++人群会告诉您什么)已经存在很长时间了:-)

您只想在库中发布足够的详细信息,以便用户有效地利用它,而不再需要更多。发布更多内容会为用户提供他们可能依赖的详细信息(例如size变量sz位于结构中的特定位置的事实,这可能会导致他们绕过控件并直接对其进行操作。

然后,当您更改内部结构时,您会发现客户苦苦抱怨。没有该结构信息,您的API仅限于您提供的内容,并且可以维护有关内部操作的自由。


1
好吧,这有什么用?
Renjith G

6
不透明的指针xyzzy,是。不透明的指针类型pmpi,不透明的结构struct pmpi。它的主要用途是与封装有关,该功能可以向用户隐藏实现细节。我将详细更新答案。
paxdiablo 2011年

1
非常感谢您的帮助。感谢您的合作。
Renjith G

2
@VinothKumar,用户应与不透明指针做的唯一的事情是得到它,或者把它传递给,该功能知道它的内部,就像fopen或者fcloseFILE *。是否FILE真正不透明取决于您在其中找到的内容stdio.h-如果已在此处完全声明它,而不仅仅是与该答案中类似的类型,则用户可以使用内部结构,因此只有经过双方同意,它才是不透明的:-)
paxdiablo

4
注意这typedef struct pmpi_s *pmpi;不是理想的:有人可能会认为例如void f(const pmpi val)其论点没有副作用,这是不正确的。
德米特里·格里戈里耶夫

9

不透明指针用于编程接口(API)的定义。

通常,它们是指向不完整结构类型的指针,声明如下:

它们的目的是为客户端程序提供一种对由API管理的对象的引用的方式,而不暴露该对象的实现(内存中的地址(指针本身)除外)。

客户端可以传递对象,将其存储在其自己的数据结构中,并比较两个这样的指针(无论它们是相同还是不同),但是它不能取消引用这些指针来窥视对象中的内容。

这样做的原因是为了防止客户端程序变得依赖于那些细节,以便可以升级实现而不必重新编译客户端程序。

由于输入了不透明指针,因此可以很好地测量类型安全。如果我们有:

如果客户端程序混合了参数的顺序,则编译器将发出诊断信息,因为astruct gadget *被转换为astruct widget *而没有强制转换。

这就是为什么我们要定义struct没有成员的类型的原因。每个struct带有不同新标签的声明都会引入一个与先前声明的struct类型不兼容的新类型。

客户变得依赖是什么意思?假设awidget_t具有width和height属性。如果它不是不透明并且看起来像这样:

然后客户只需执行以下操作即可获得宽度和高度:

而在不透明的范式下,它必须使用访问函数(未内联):

请注意,widget作者是如何使用该short类型来节省结构中的空间的,并且该类型已暴露给非透明接口的客户端。假设小部件现在可以具有不适合的大小,short并且结构必须更改:

现在必须重新编译客户端代码以采用此新定义。根据工具和部署工作流程的不同,甚至可能存在未完成的风险:旧的客户端代码尝试使用新的库,并且通过使用旧的布局访问新的结构而行为不端。对于动态库,这很容易发生。库已更新,但相关程序未更新。

使用不透明接口的客户端可以继续工作而不做修改,因此不需要重新编译。它只是调用访问器函数的新定义。这些位于小部件库中,并且可以int从结构中正确检索新键入的值。

请注意,从历史上(至今仍在此)存在使用该void *类型作为不透明句柄类型的乏味做法:

在此方案下,您可以执行此操作,而无需任何诊断:

Microsoft Windows API是系统的示例,您可以在两种系统中同时使用它。默认情况下,各种句柄类型均为HWND(窗口句柄)和HDC(设备上下文)void *。因此,没有类型安全性。一个HWND可以通过其中HDC的预期,按错。如果您这样做:

然后将这些句柄映射到互不兼容的类型以捕获这些错误。


2

顾名思义,不透明是我们看不到的。例如,木材是不透明的。不透明指针是指向数据结构的指针,该数据结构的内容在定义之时不公开。

例:

分配NULL给不透明的指针是安全的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.