如何在C中使用不透明指针?

时间:2016-02-02 20:17:41

标签: c pointers

我在线阅读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结构?请帮帮我!

4 个答案:

答案 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

相关问题