我在线阅读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结构指针 - 期望不透明指针指向与结构指针相同的位置,但这似乎是错误的。尝试使用' - >'进行计数。给出错误"试图访问会员'计数'在某些东西不是结构或联合"
如何使void Opaque指针引用我的list_t结构?请帮帮我!
答案 0 :(得分:3)
您的代码存在一些问题。首先,d_link_list_t已经是一个void指针,因此在定义不透明指针时使用
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;
最后,在最后,为什么要尝试通过opaque指针访问struct的内容。为什么这个
list->count = 0; //list IS NOT STRUCT
创建不透明指针的整个想法是,用户无法直接访问该结构。如果要访问struct,请使用实际指针或将opaque指针强制转换为指向struct的指针。同样,整个想法是从您的函数用户隐藏列表的内部实现。
答案 1 :(得分:2)
这一行错了:
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行中删除*
。
答案 2 :(得分:1)
不透明指针就像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在不破坏任何现有代码的情况下进行更改,因为您知道没有人可以篡改结构的私有。
这也可以使用Handle Body Idiom在C ++中应用。
答案 3 :(得分:0)
您不需要(void *)
,只需使用
typedef struct list_s list_t;
在您的头文件中,并在.c文件中定义struct list_s
。