我有以下代码:
struct DataBase {
union manip_types *manip;
};
union manip_types{
void ( *man_insert )( struct DataBase *, struct auto_increment *, enum db_insert_types,... );
void ( *man_remove )( struct DataBase *, struct auto_increment *, enum db_remove_types, int );
void ( *man_update )( struct DataBase *, enum db_update_types, int,... );
union db_query_union ( *man_query )( struct DataBase *, enum db_query_types, int );
struct db_query_extended ( *man_query_ex )( struct DataBase *, struct auto_increment *, enum db_query_types,... )
};
然后我做了:
db->manip = malloc( 5 * sizeof( union manip_types ) );
db->manip[ 0 ].man_insert = &db_insert;
db->manip[ 1 ].man_remove = &db_remove;
db->manip[ 2 ].man_update = &db_update;
db->manip[ 3 ].man_query = &db_query;
db->manip[ 4 ].man_query_ex = &db_query_ex;
上面的代码为每个 [0, 1, -> 4] 生成以下警告
Assignment from incompatible pointer type.
函数原型(prototype):
void db_insert( struct DataBase *db, struct auto_increment *a_i, enum db_insert_types db_insert_type,... )
void db_remove( struct DataBase *db, struct auto_increment *a_i, enum db_remove_types db_remove_type, int removeId )
void db_update( struct DataBase *db, enum db_update_types db_update_type, int upId,... )
union db_query_union db_query( struct DataBase *db, enum db_query_types db_query_type, int queryId )
struct db_query_extended db_query_ex( struct DataBase *db, struct auto_increment *a_i, enum db_query_types db_query_type,... )
我应该修改什么?我如何调用该指针数组?例如,v[4]。
最佳答案
您可以声明一个通用函数指针数组,而不是尝试使用这样的 union 数组,例如:
void (*manip[5])();
或者,如果您想动态分配数组:
void (**manip)() = malloc(5 * sizeof( void(*)() ));
并将所有函数指针转换为泛型类型void(*)()
:
manip[0] = (void(*)()) &db_insert;
manip[1] = (void(*)()) &db_remove;
manip[2] = (void(*)()) &db_update;
manip[3] = (void(*)()) &db_query;
manip[4] = (void(*)()) &db_query_ex;
当然,要调用这些函数,您需要将它们转换回正确的类型,例如:
void (*update)(struct DataBase *, enum db_update_types, int, ...)
= (void (*)(struct DataBase *, enum db_update_types, int, ...)) manip[2];
update(db, type, n, etc);
为了可读性和可维护性,您可能希望将这些函数签名键入为更具可读性,例如:
typedef void ( *man_insert_t )( struct DataBase *, struct auto_increment *, enum db_insert_types,... );
typedef void ( *man_remove_t )( struct DataBase *, struct auto_increment *, enum db_remove_types, int );
typedef void ( *man_update_t )( struct DataBase *, enum db_update_types, int,... );
typedef union db_query_union ( *man_query_t )( struct DataBase *, enum db_query_types, int );
typedef struct db_query_extended ( *man_query_ex_t )( struct DataBase *, struct auto_increment *, enum db_query_types,... );
让你简单地写
man_update_t update = (man_update_t) manip[2];
update(db, type, n, etc);
或者甚至只是:
((man_update_t) manip[2])(db, type, n, etc);
当然,在实践中,正确的解决方案是将数组替换为结构体,这样您就可以避免所有这些类型转换技巧:
struct db_manip {
void ( *insert )( struct DataBase *, struct auto_increment *, enum db_insert_types,... );
void ( *remove )( struct DataBase *, struct auto_increment *, enum db_remove_types, int );
void ( *update )( struct DataBase *, enum db_update_types, int,... );
union db_query_union ( *query )( struct DataBase *, enum db_query_types, int );
struct db_query_extended ( *query_ex )( struct DataBase *, struct auto_increment *, enum db_query_types,... );
};
struct db_manip *manip = malloc(sizeof(struct db_manip));
manip->insert = &db_insert;
manip->remove = &db_remove;
manip->update = &db_update;
manip->query = &db_query;
manip->query_ex = &db_query_ex;
关于来自不兼容指针类型的 C 指针数组赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40935914/