gpt4 book ai didi

通过结构数组中的函数指针调用函数

转载 作者:太空宇宙 更新时间:2023-11-04 06:58:22 25 4
gpt4 key购买 nike

我是 C 的新手,我正在尝试创建一个包含函数指针的结构数组。

直接从结构调用函数(并访问成员)按预期工作,但通过循环访问它从数组访问它不会(访问成员工作)。

我已经发现了一个类似的问题,但我想知道为什么当我尝试通过访问数组中的函数来调用我的函数时,我从各种教程和帖子中整理出来的程序崩溃了。

结构.h

typedef struct {
char *functionId;
void (*callback)(unsigned char *data);
char *name;
char *description;
} Function;

typedef struct {
Function *fArr;
size_t used;
size_t size;
} Array;

主.c

   #include <stdio.h>
#include <stdlib.h>

#include "structs.h"

Array functionArray;

void function1(int *i){
printf("PRINT: %d\n", i);
}

void function2(char *c[]){
printf("PRINT: %s\n", c);
}

void addFunction(Function f){
insertFunctionArray(&functionArray, f);
}

int main()
{
initFunctionArray(&functionArray, 5);

//create new struct for function and assign function to callback member
Function fun;
fun.name = "Function1";
fun.functionId = "FUNCTION1";
fun.description = "Description for Function 1";
fun.callback = &function1; // <-- doesn't seem to matter if I assign it as a value or as a pointer?!

Function fun2;
fun2.name = "Function2";
fun2.functionId = "FUNCTION2";
fun2.description = "Description for Function 2";
fun2.callback = &function2;

fun2.callback("{fun:\"test\"}");

fun.callback(17);

//store functions in array
addFunction(fun);
addFunction(fun2);

unsigned int i = 0;
for(i; i<functionArray.used; i++)
{
printf("PRINT: %s\n", functionArray.fArr[i].functionId); // <-- this works
functionArray.fArr[i].callback("777"); // <-- this doesn't work
}
}

return 0;
}

void initFunctionArray(Array *fa, size_t initialSize) {
fa->fArr = (Function *)malloc(initialSize * sizeof(Function));
fa->used = 0;
fa->size = initialSize;
unsigned int i = 0;
for(i; i<initialSize; i++)
{
memset(&fa->fArr[i],0,sizeof(Function));
}
}

void insertFunctionArray(Array *fa, Function f) {
if (fa->used == fa->size) {
fa->size *= 2;
fa->fArr = (Function *)realloc(fa->fArr, fa->size * sizeof(Function));
}
// Copy name
fa->fArr[fa->used].name = (char*)malloc(strlen(f.name) + 1);
strcpy(fa->fArr[fa->used].name, f.name);
// Copy ID
fa->fArr[fa->used].functionId=f.functionId;
fa->used++;
}

谢谢&BR

最佳答案

此代码重新设计函数以获取 void *然后,在没有修复的情况下,由于您没有分配 callback 这个微不足道的问题而令人信服地崩溃了。当你复制 FunctioninsertFunctionArray() .修复很简单——分配回调:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
char *functionId;
void (*callback)(void *data);
char *name;
char *description;
} Function;

typedef struct
{
Function *fArr;
size_t used;
size_t size;
} Array;

void initFunctionArray(Array *fa, size_t initialSize);
void insertFunctionArray(Array *fa, Function f);

Array functionArray;

static void function1(void *vp)
{
int *i = vp;
printf("PRINT: %d\n", *i);
}

static void function2(void *vp)
{
char *s = vp;
printf("PRINT: %s\n", s);
}

static void addFunction(Function f)
{
insertFunctionArray(&functionArray, f);
}

int main(void)
{
initFunctionArray(&functionArray, 5);

// create new struct for function and assign function to callback member
Function fun;
fun.name = "Function1";
fun.functionId = "FUNCTION1";
fun.description = "Description for Function 1";
fun.callback = &function1; // <-- doesn't seem to matter if I assign it as a value or as a pointer?!

Function fun2;
fun2.name = "Function2";
fun2.functionId = "FUNCTION2";
fun2.description = "Description for Function 2";
fun2.callback = &function2;

fun2.callback("{fun:\"test\"}");

int v = 17;
fun.callback(&v);

// store functions in array
addFunction(fun);
addFunction(fun2);

for (size_t i = 0; i < functionArray.used; i++)
{
printf("PRINT: %s (%p)\n", functionArray.fArr[i].functionId, (void *)functionArray.fArr[i].callback);
functionArray.fArr[i].callback("777");
}

return 0;
}

void initFunctionArray(Array *fa, size_t initialSize)
{
fa->fArr = (Function *)malloc(initialSize * sizeof(Function));
fa->used = 0;
fa->size = initialSize;
for (size_t i = 0; i < initialSize; i++)
{
memset(&fa->fArr[i], 0, sizeof(Function));
}
}

void insertFunctionArray(Array *fa, Function f)
{
if (fa->used == fa->size)
{
fa->size *= 2;
fa->fArr = (Function *)realloc(fa->fArr, fa->size * sizeof(Function));
}
// Copy name
fa->fArr[fa->used].name = (char *)malloc(strlen(f.name) + 1);
strcpy(fa->fArr[fa->used].name, f.name);
// Copy ID
fa->fArr[fa->used].functionId = f.functionId;
// Fix!
fa->fArr[fa->used].callback = f.callback;
fa->used++;
}

输出:

PRINT: {fun:"test"}
PRINT: 17
PRINT: FUNCTION1 (0x10c724af0)
PRINT: 3618615
PRINT: FUNCTION2 (0x10c724ad0)
PRINT: 777

注意:代码在带有 GCC 6.2.0(必须升级!)的 macOS Sierra 10.12.2 上使用命令行编译干净:

$  gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition str19.c -o str19 

其他变化

callback函数指针被修改为 void *参数而不是 unsigned char * .两个回调函数,function1function2是为了匹配回调接口(interface)——他们采用 void *参数并将其转换为适当的类型。 function2 上有一个额外的间接级别那去了路边。直接调用function1通过 fun.callback必须改变结构;您不能传递简单数字常量的地址。 (我想你可以使用“复合文字”:fun.callback(&(int){ 17 });。)我需要 <string.h>申报strlen() .

几乎所有其他内容都没有改变。

请注意,我做的第一件事就是在调用之前将函数指针地址添加到打印操作。当我得到 0x0 ,没过多久就找出了问题所在。

请注意 function1function2最终被调用 "777"作为论据。这就是为什么我得到 3618615作为 function1 的输出在循环内。这不好——(不幸的是)C 容忍这样的错误。

另请注意,代码会泄漏大量内存。它或多或少是一个 MCVE,所以这或多或少是可以原谅的。

关于通过结构数组中的函数指针调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41516107/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com