《C语言接口与实现》:关于不透明指针
在《C语言接口与实现:创建可重用软件的技术》一书中,提到了不透明指针:
C语言中常使用typedef定义,比如:
typedef struct stack *stack_t;
该定义表示一个指向栈结构的指针,但并没有给出结构的任何信息,所以stack_t是一个不透明指针类型,客户程序可以自由的操纵这种指针,但无法反引用,即无法查看指针所指向结构的内部信息,只有接口的实现才有这种特权。
好处:不透明指针隐藏了实现细节,有助于捕获错误。即只能传相同类型的参数给函数,否则将产生变异错误。例外是参数中有void型指针
void *型指针作为一种通用的指针,可以和其它任何类型的指针(函数指针除外)相互转化而不需要类型强制转换,但不能对它进行解引用及下标操作。C语言中的malloc函数的返回值就是一个void *型指针,我们可以把它直接赋给一个其他类型的指针,但从安全的编程风格角度以及兼容性上讲,最好还是将返回的指针强制转换为所需的类型,另外,malloc在无法满足请求时会通过返回一个空指针来作为“内存分配失败”的信号,所以要注意返回值指针的判空。
该书经常使用类似如下代码
#define T Stack_T
typedef struct T *T;
...
#undef T
用T去封装ADT接口中的主要类型,上面的代码的意思是:
(1)有一个结构体Stack_T;
(2)有一个指针,命名也是Stack_T,并且指向结构体Stack_T;
(3)T也就是Stack_T。
这种用法作者称为语法糖(syntactic sugar),但我个人认为不是多必要,虽然可以封装到接口并且是库里一致,但容易导致误读,用的时候到底Stack_T是结构还是指针?尤其是需要对库作修改时会容易出错。我觉得如下写法更好:
typedef struct stack_t
{
...
}STACK, * STACKP;
其中stack_t是结构体,STACK是定义的结构体类型,STACKP是stack_t结构指针,使用如下:
STACK stc;//结构体
STACKP pstc;//结构体指针