【问题标题】:Why we cannot dynamically allocate a pointer to a function?为什么我们不能动态分配指向函数的指针?
【发布时间】:2018-01-22 20:00:57
【问题描述】:

我试图动态分配一个指向类似函数的指针

void (*f)(void*);
f = (*f)malloc(sizeof(f) * 2);

我遇到了一个错误。

错误:预期为 ';'在“malloc”之前

查了一下,发现不能动态分配函数指针,只能像数组一样声明。在第一步中,我将它声明为一个函数数组

void (f[2])(void*);

我看到另一个错误,我无法声明函数数组,我必须将其声明为函数指针数组。

void (*f[2])(void*);

在我的搜索中我也发现,指向函数的指针并不指向数据,而是指向代码。 如果有人能解释一下为什么我们不能动态分配指向函数的指针以及为什么我们不能拥有函数数组而不是函数指针数组。

我的代码如下:

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

void printNr(void *nr)
{
    printf("%i\n", nr);
}

void printChar(void *ch)
{
    printf("%c\n", ch);
}

int  main(void)
{
    void (*f)(void*);
    f = (*f)malloc(sizeof(f) * 2);
    f = printNr;
    (f  + 1) = printChar;
    (*f)(15);
    (*(f  + 1))('t');
    return (0);
} 

【问题讨论】:

  • 你能分享一下错误吗?我猜这是因为您没有分配指向指针的指针
  • 请提供一个简短的示例程序,其中包含您在帖子中尝试执行的操作的完整源代码。还要指出你真正想要完成的是什么。您可以创建一个变量,然后为其分配一个指向函数的指针,但是您不能动态创建函数、lambda 或闭包,并将其分配给 C 中的变量。
  • 您似乎对指针指针指向的对象之间的区别感到困惑。函数指针指向一个函数。不能动态分配函数。
  • @Xtx sizeof 运算符可能不适用于函数。因此,您可能不会声明函数数组。例如,函数定义在编译时可能是未知的。
  • 编译器在malloc 之前抱怨(*f)。那不是演员表(反正也不需要演员表)。

标签: c arrays function pointers malloc


【解决方案1】:

如果您想为指向ints 的指针数组动态分配空间,则需要双 **(指向指针的指针)

int **arr = malloc(sizeof(*arr) * n);

对于指向函数的指针数组也是如此,您需要一个双 ** 然后取消引用以获取 sizeof

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

void fn1(void *val)
{
    puts((char *)val);
}

void fn2(void *val)
{
    puts((char *)val);
}

int main(void)
{
    void (**f)(void*);

    f = malloc(sizeof(*f) * 2);
    f[0] = fn1;
    f[1] = fn2;
    f[0]("Hello");
    f[1]("Bye");
    free(f);
    return 0;
}

【讨论】:

    【解决方案2】:

    澄清一下——

    1. 为函数分配内存是不合逻辑的,因为你不会在那里复制函数的代码:)*1。您只需分配函数所在的内存地址。函数已在内存中。
    2. 您无法创建函数数组,原因与1. 中的相同。您只能创建指向函数的指针数组。

    *在嵌入式开发中,如果函数必须从 RAM 中运行,有时会使用它,RAM 是有限的,需要释放给另一个。但通常是静态存储位置,而不是动态的。

    【讨论】:

      【解决方案3】:

      在您定义的两个函数中存在各种定义不明确(如果不是实际上未定义)的行为。使用该代码,您(充其量)过着危险的生活。您可以将函数定义为采用int,然后就可以了(也可以更改函数指针类型)。

      但是,我想这与您的直接问题无关——(*f) 之前的 malloc() 完全是虚假的。如果你想在那里进行强制转换,你需要(void (**)(void *)) 指定一个指针,该指针指向一个返回void 并采用void * 参数的函数。

      这里是按照建议更改函数类型的固定代码:

      #include <stdio.h>
      #include <stdlib.h>
      
      static void printNr(int nr)
      {
          printf("%i\n", nr);
      }
      
      static void printCh(int ch)
      {
          printf("%c\n", ch);
      }
      
      int main(void)
      {
          void (**f)(int);
          f = (void(**)(int))malloc(sizeof(*f) * 2);
          f[0] = printNr;
          f[1] = printCh;
          (*f)(15);
          (*(f  + 1))('t');
          free(f);
          return(0);
      }
      

      请注意,分配(f[0]f[1])也已修复。如果您必须使用非数组表示法,那么 *(f + 0)*(f + 1) 将是自洽的,*f*(f+1) 也可以工作。

      使用 typedef 作为指向函数类型的指针会更容易。

      #include <stdio.h>
      #include <stdlib.h>
      
      typedef void (*FunctionPtr)(int);
      
      static void printNr(int nr)
      {
          printf("%i\n", nr);
      }
      
      static void printCh(int ch)
      {
          printf("%c\n", ch);
      }
      
      int main(void)
      {
          FunctionPtr *f = (FunctionPtr *)malloc(sizeof(*f) * 2);
          f[0] = printNr;
          f[1] = printCh;
          (*f)(15);
          (*(f  + 1))('t');
          free(f);
          return(0);
      }
      

      请注意,在定义函数时不能使用 typedef。即使您定义了函数类型而不是函数指针类型,您也不能这样做,这是 C 的一个奇怪的怪癖。例如,给定typedef void Function(int);,您不能定义static Function printNr { … } 或任何类似的东西,并且它的含义与定义的函数相同。尝试static Function *returnsPtr(int n) { … } 编译(如果主体合适)但返回一个函数指针(Function *FunctionPtr)。

      如果您使用的是 C 编译器,则不需要来自 malloc() 的强制转换。如果您使用的是 C++ 编译器,则需要它。代码(两个程序)释放分配的内存。两个程序都没有检查分配——拍手腕。

      【讨论】:

        猜你喜欢
        • 2021-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-02
        • 1970-01-01
        • 1970-01-01
        • 2013-05-26
        • 1970-01-01
        相关资源
        最近更新 更多