K. *_*ann 1 c struct pointers casting type-conversion
我有一些struct像这样的:
struct myStruct0 {
void(*deallocMe)(void*); // points always to "myStruct0_dealloc"
uint8_t* someStuff;
void* someOtherStuff;
}
void myStruct0_dealloc(void* structPtr) {
myStruct0* s = (myStruct0*)structPtr;
free(s->someStuff);
free(s->someOtherStuff);
free(s);
}
struct myStruct1 {
void(*deallocMe)(void*); // points always to "myStruct1_dealloc"
uint8_t* someStuff;
uint64_t largeArray[4096];
void* someOtherStuff;
char* someRealOtherStuff;
}
void myStruct1_dealloc(void* structPtr) {
myStruct1* s = (myStruct1*)structPtr;
free(s->someStuff);
free(s->someOtherStuff);
free(s->someRealOtherStuff);
free(s);
}
Run Code Online (Sandbox Code Playgroud)
无论structS和指针使用分配的malloc(当然不能是NULL).
以下代码是否安全?
struct genericForm {
void(*deallocMe)(void*);
}
void deallocMyStructX(void* myStructX) {
genericForm* x = (genericForm*)myStructX;
x->deallocMe(myStructX);
}
Run Code Online (Sandbox Code Playgroud)
我为什么要这样做?
我将有一个struct像上面的一些指针的数组,如果这将工作,我不必为每个struct/指针保存deallocator .这将真正简化我的代码.
编辑:结构可以完全不同.他们唯一共享的是它们包含表单的函数指针void(*)(void*)作为第一个元素.
如果您只想访问结构的第一个成员,那么您应该没问题.第一个成员的偏移量保证为0,如果第一个成员与所有结构(即函数指针)兼容,那么你应该没问题.如果您要取消引用结构并访问其他成员,则可能会因填充而遇到问题.添加占位符成员可能会解决这个问题,但可能有点低效.
如果你没有太多的结构要担心,这可能是一个更简单的解决方案:
struct _data {
int identifier;
union {
struct type_1 {} _t1;
struct type_2 {} _t2;
struct _generic {
void (*dealloc_generic)(void *);//first member is dealloc function pointer
} _gen;
};
};
void dealloc_struct(struct _data * s)
{
switch (s->identifier)
{
case 1:
s->t1->delloc_t1_ptr(s->t1);
return;
//and so on
default:
//for generic-compatible structs
s->_gen->delloc_generic(s->_gen);
}
}
Run Code Online (Sandbox Code Playgroud)
如果你的结构的第一个成员将始终是一个有效的函数指针,那么你甚至可以这样写:
void dealloc_struct(void *s)
{
//cast s to function pointer, call it and pass the pointer as argument
((void (*)(void *))s)(s);
}
Run Code Online (Sandbox Code Playgroud)
根据标准(C1x§6.7.2.1.13),这应该有效:
指向适当转换的结构对象的指针指向其初始成员[...],反之亦然.在结构对象中可能存在未命名的填充,但在其开头不是.