【问题标题】:Malloc an array of function pointersmalloc 函数指针数组
【发布时间】:2015-12-06 07:05:31
【问题描述】:

我有一个函数数组,需要在运行时分配以便按顺序调用。哪个函数指针在哪个位置是通过程序确定的,例如:

void ((drawFunctions*)(...))[0] = drawTriangle;
...
for(...)
    drawFunctions[i](...);

我想 malloc 一个函数指针数组,因为直到运行时我才知道需要多少个。你会怎么做呢?

【问题讨论】:

  • 所有函数都采用相同的参数吗? “...”是表示省略的代码还是字面意思是“...”表示它们是可变参数?
  • 您最好编辑您的问题以获得真正的 C99 代码并避免使用您的 ...
  • 据我所知,省略号的唯一含义是“用有意义的东西填空”。省略号总结了与问题无关的内容,只会占用空间。
  • 可变函数,对吧?很有趣。

标签: c arrays function-pointers


【解决方案1】:

typedef 可能会使语法更容易接受:

typedef void (*drawFunctionPointer)(void);
drawFunctionPointer *drawFunctions = malloc(sizeof(drawFunctionPointer) * numFunctions);

【讨论】:

  • 好的,现在如何初始化这个指针?我试过这个,但我收到警告。 FPTR *cr1_task_fptr = malloc(CR1_TASKS*sizeof(FPTR)); (cr1_task_fptr) = (FPTR){&function1, &function2, &function3, &function4}; 它说:警告:标量初始化程序中的多余元素
【解决方案2】:

首先,在 C99 中,variadic function 应该至少有一个第一个非可变参数(例如 printf 有一个 const char*fmt 第一个参数)。见stdarg(3)

然后,为了便于阅读,我将使用typedef 来声明函数签名,例如

 typedef void drawfun_sigt (int, ...);

声明一个变量保存指向指针数组的指针:

 drawfun_sigt** parr = NULL;

分配它(并处理失败):

 size_t nbfun = somenumber();
 parr = malloc(nbfun*sizeof(drawfun_sigt*));
 if (!parr) { perror("malloc"); exit(EXIT_FAILURE); };

清除它(为了使行为更可重现,我不喜欢malloc-ed 数组中未初始化的元素;但cmaster 评论说valgrind 会发现这些错误);你可以使用calloc 而不是malloc

 memset (parr, 0, nbfun*sizeof(drawfun_sigt*));

然后适当填写

 extern void drawfunfoo(int, ....);
 parr[0] = drawfunfoo;

当然,获取函数地址的方法有很多。在 POSIX 系统(尤其是 Linux)上,您甚至可以使用 dlopen(3)dlsym(3) 的名称​​动态获得这样的地址

如果您的函数指针具有完全未知的签名(即,如果省略号 ... 在您的问题中的含义不是可变参数函数),您应该使用 libffi(或者,如果签名集已知,则使用union 的函数指针)。请注意,您的 C 实现中的 calling convention(和 ABI)可能(并且经常这样做)规定了调用具有不同签名的函数的不同方式。例如,Linux 的x86-64 ABI 要求以不同方式调用可变参数函数和非可变参数函数,并在寄存器中传递一些形式参数(整数和浮点的不同寄存器)。

【讨论】:

  • 如果您打算在 malloc 之后立即将其归零,有什么理由不使用 calloc
  • 因为 OP 想要malloc。确实我更喜欢calloc
  • malloc 之后将内存归零对我来说似乎毫无意义除非您实际使用这些零。读取尚未写入的分配部分始终是错误的,并确保您只有零可读取可能只会掩盖错误。更重要的是:如果您使用零内存分配valgrind 将不再发现这些错误。如果没有归零,它将报告未初始化数据的使用。通过归零,valgrind 会看到您在读取之前主动初始化内存,因此它不会响起警报。所以,calloc() 在避免 bug 方面确实适得其反。
  • 真正的程序员不使用 valgrind :)))))))))(开玩笑)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
相关资源
最近更新 更多