从函数返回指向结构的指针

时间:2018-12-04 06:33:10

标签: c struct memcpy

我使用一些声明一些不透明类型的库。我将此类型包装到自己的结构中以对该库的不透明类型进行抽象处理,并遇到了一些问题。这是代码:

typedef struct my_struct my_struct;
struct my_struct{
    opaque_lib_t *const opaque_lib_ptr; //opaque_lib_t is the opaque type
                                        //came from the library
};

my_struct* initialize(){
    opaque_lib_t *opaque_lib_ptr;
    init(&opaque_lib_ptr);              //library function call
    return opaque_lib_ptr;
}

void use_and_release(my_struct *my_struct_ptr){
     //use and release my_struct
}

my_struct *my_struct_ptr =  initialize();
use_and_release(my_struct_ptr);         //crashes

在这样的实现中,对use_and_release的调用崩溃。因此,我尝试用以下实现方式替换my_struct* initialize

my_struct* initialize(){
     opaque_lib_t *opaque_lib_ptr;
     init(&opaque_lib_ptr);
     my_struct *my_struct_ptr = malloc(sizeof(*my_struct_ptr));
     my_struct tmp = {.opaque_lib_ptr = opaque_lib_ptr};
     memcpy(my_struct_ptr, &tmp, sizeof(tmp));
     return my_struct_ptr;
}

通过这样的实现,它可以正常工作。但是我不明白为什么第一个不起作用。我认为指向结构的指针和指向其第一个元素的指针具有相同的值。因此,在这种情况下,最好返回opaque_lib_t*并将其强制转换为my_struct*,因为my_struct*仅包含一个元素。

1 个答案:

答案 0 :(得分:3)

为什么要尝试第一个示例,是一种尝试模仿面向对象语言的继承的方式。似乎您想让my_structopaque_lib_t建立“是”关系。

但是这行不通,因为然后您需要my_struct的第一个成员成为opaque_lib_t结构的实际 instance ,即应该是

struct my_struct{
    opaque_lib_t opaque_lib_instance;   //opaque_lib_t is the opaque type
                                        //came from the library
};

如果opaque_lib_t确实是类似于FILE的匿名且不透明的结构,则不可能。

另一种看待方式是这样的:

内存my_struct看起来像

my_struct             opaque_lib_t
+----------------+    +-------------------+
| opaque_lib_ptr | -> | Unknown data      |
+----------------+    | More unknown data |
                      | ...               |
                      +-------------------+

您根本无法将opaque_lib_t覆盖在my_struct之上。

当您进行return opaque_lib_ptr;时,您实际上是在说“此指针指向第一个成员是指向my_struct的指针opaque_lib_t”。这完全是错误的,因为这是两个非常不同的结构。

继续执行第一段代码,如果您尝试使用my_struct_ptr->opaque_lib_ptr,则访问的内存是opaque_lib_t结构的初始数据(返回的指针)。


最后关于你说的话

  

在我的代码中,我想对特定库结构进行抽象

我可以理解,但这已经是opaque_lib_t的目的。您可以在抽象之上添加(不必要的)抽象。

如果它收集了与多个相关的数据,而不仅是opaque_lib_t指针,我可以理解您的结构。