从函数返回指向结构的指针
Returning a pointer to a structure from function
我使用了一些声明了一些不透明类型的库。我将这种类型包装到我自己的结构中以抽象出这个库不透明类型并遇到了一些问题。这是代码:
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;
}
有了这样的实现,它工作正常。但我不明白为什么第一个不起作用。我认为指向结构的指针和指向其第一个元素的指针具有相同的值。所以在这种情况下,只 return opaque_lib_t*
并将其转换为 my_struct*
应该没问题,因为 my_struct*
只包含一个元素。
为什么你尝试用你的第一个例子来尝试模拟面向对象语言的继承。您似乎希望 my_struct
与 opaque_lib_t
.
建立 "is a" 关系
但是这行不通,因为你需要 my_struct
的第一个成员是 opaque_lib_t
结构的实际 实例 ,即它应该是
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;
时,你实际上是在说 "this pointer is pointing to a my_struct
whose first member is a pointer to opaque_lib_t
"。这是完全错误的,因为它们是两个截然不同的结构。
继续第一段代码,如果你尝试使用my_struct_ptr->opaque_lib_ptr
那么你访问的内存就是opaque_lib_t
结构的初始数据(你返回了它的指针)。
最后说一下
In my code I want to abstract over the specific library structures
我能理解,但这已经是opaque_lib_t
的目的了。您在抽象之上添加了(不必要的)抽象。
如果它收集了 多个 相关数据,而不仅仅是 opaque_lib_t
指针,我就能理解你的结构。
我使用了一些声明了一些不透明类型的库。我将这种类型包装到我自己的结构中以抽象出这个库不透明类型并遇到了一些问题。这是代码:
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;
}
有了这样的实现,它工作正常。但我不明白为什么第一个不起作用。我认为指向结构的指针和指向其第一个元素的指针具有相同的值。所以在这种情况下,只 return opaque_lib_t*
并将其转换为 my_struct*
应该没问题,因为 my_struct*
只包含一个元素。
为什么你尝试用你的第一个例子来尝试模拟面向对象语言的继承。您似乎希望 my_struct
与 opaque_lib_t
.
但是这行不通,因为你需要 my_struct
的第一个成员是 opaque_lib_t
结构的实际 实例 ,即它应该是
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;
时,你实际上是在说 "this pointer is pointing to a my_struct
whose first member is a pointer to opaque_lib_t
"。这是完全错误的,因为它们是两个截然不同的结构。
继续第一段代码,如果你尝试使用my_struct_ptr->opaque_lib_ptr
那么你访问的内存就是opaque_lib_t
结构的初始数据(你返回了它的指针)。
最后说一下
In my code I want to abstract over the specific library structures
我能理解,但这已经是opaque_lib_t
的目的了。您在抽象之上添加了(不必要的)抽象。
如果它收集了 多个 相关数据,而不仅仅是 opaque_lib_t
指针,我就能理解你的结构。