我正在在线浏览 C 书,我不明白结构指针上的 6.6。我正在尝试在初始化函数中返回指向双向链表的指针,但迷失了方向。
.h 有一个不透明的指针指向引用双向链表:
typedef void * d_link_list_t;
.c 实现具有列表结构定义:
typedef struct list_s
{
node_t * head;
node_t * tail;
int count; //num nodes
} list_t
.c后来我实现了初始化函数,其中问题是:
d_link_list_t* Initialize(void)
{
//Converting opaque pointer to real pointer
d_link_list_t* list = (d_link_list_t*)malloc(sizeof(d_link_list_t*));
// Now make concrete list_t pointer and set the members
list_t * rlP;//real list pointer
rlP = (list_t*)malloc(sizeof(list_t));
rlP->head = NULL;
rlP->tail = NULL;
rlP->count = 1;
//cast opaque pointer to real list P PROBLEM HERE
list = (d_link_list_t*)rlP;
list->count = 0; //list IS NOT STRUCT
return list;
}
我想返回 * d_link_list_t
,一个不透明的指针,它将引用链表的实例。我希望 implementation.c 中的所有函数都使用 .h 中这个不透明指针引用的列表。 我根本不明白该怎么做。
我尝试只是将不透明指针投射到 list_t 结构指针 - 期望不透明指针指向与结构指针相同的位置,但这似乎是错误的。尝试使用"->"访问计数会给出错误"尝试在非结构或联合中访问成员'count'">
如何使空不透明指针引用我的list_t结构?请帮帮我!
你的代码有几个问题。首先,d_link_list_t已经是一个空指针,所以当你定义你的不透明指针时,使用
d_link_list_t list; //list is a void pointer
and not
d_link_list_t* list; //list is a pointer to a void pointer.
其次,我认为这段代码
//Converting opaque pointer to real pointer
d_link_list_t* list = (d_link_list_t*)malloc(sizeof(d_link_list_t*));
应该为不透明的指针分配空间,但你不需要这样做,正如我之前所说,只需使用
d_link_list_t list; //list is a void pointer.
第三,当您将真实指针投射到不透明指针时,您还需要在函数结束时调整转换。用
list = (d_link_list_t)rlP;
而不是
list = (d_link_list_t*)rlP;
最后,在最后,为什么要尝试通过不透明的指针访问结构的内容。为什么会这样
list->count = 0; //list IS NOT STRUCT
创建不透明指针的整个想法是使用户无法直接访问结构。如果要访问结构,请使用实指针或将不透明指针强制转换为指向结构的指针。同样,整个想法是对函数的用户隐藏列表的内部实现。
这一行是错误的:
d_link_list_t* list = (d_link_list_t*)malloc(sizeof(d_link_list_t*));
它分配了错误的内存量。您需要分配所指向事物的大小,而不是指针的大小。
然而,无论如何,这是一个坏主意。该函数应为:
d_link_list_t Initialize(void)
{
// Now make concrete list_t pointer and set the members
list_t * rlP;
rlP = malloc(sizeof(*rlP));
rlP->head = NULL;
rlP->tail = NULL;
rlP->count = 1;
return rlP;
}
不确定您要用list->count = 0;
做什么,因为list
具有不透明类型,这是不可能的。 也不清楚你为什么写rlP->count = 1
而不是= 0
.
如果要使用指针语法(即 d_link_list_t *
(,则应从 typedef 行中删除*
。
你不需要(void *)
,你应该简单地使用
typedef struct list_s list_t;
,然后在 .c 文件中定义struct list_s
。
不透明的指针类似于 C FILE
结构。在 Microsoft C 中,FILE
结构为
typedef struct _iobuf {
void *_Placeholder;
} FILE;
请注意,没有实际字段,唯一的成员是void *
。此指针实际上指向位于 Microsoft C 实现深处的秘密结构。假设它看起来像这样
typedef struct {
int cnt;
char *ptr;
char *base;
int flag;
int fd;
} impfile;
然后,对FILE
指针进行操作的函数将_Placeholder
成员强制转换为impfile
结构。例如,访问文件描述符的函数如下所示:
int getfd(FILE *fp)
{
return ((impfile *) fp->_Placeholder)->fd;
}
Windows API 通过句柄使用类似的技术,如 HWND
。
此方法的优点是用户无法访问任何私有成员。这也允许 API 在不破坏任何现有代码的情况下进行更改,因为您知道没有人可以篡改结构的私有结构。
这也可以在使用句柄正文习惯用法应用于C++。