我有一些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); }
无论struct
S和指针使用分配的malloc(当然不能是NULL).
以下代码是否安全?
struct genericForm { void(*deallocMe)(void*); } void deallocMyStructX(void* myStructX) { genericForm* x = (genericForm*)myStructX; x->deallocMe(myStructX); }
我为什么要这样做?
我将有一个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); } }
如果你的结构的第一个成员将始终是一个有效的函数指针,那么你甚至可以这样写:
void dealloc_struct(void *s) { //cast s to function pointer, call it and pass the pointer as argument ((void (*)(void *))s)(s); }
根据标准(C1x§6.7.2.1.13),这应该有效:
指向适当转换的结构对象的指针指向其初始成员[...],反之亦然.在结构对象中可能存在未命名的填充,但在其开头不是.