繁体   English   中英

如何在C中使用两个返回不同类型的函数作为函数指针?

[英]How to use two functions that return different types as a function pointer in C?

我有一个create函数,我想传递一个函数指针,但是我希望该函数指针能够调用以下我遇到的问题之一,即每个函数都返回不同的类型。 但是,当我传递函数指针时,我必须指定函数指针的返回类型。 这个对吗? 我认为在中使用空指针将解决返回类型问题,但是现在我无法调用函数指针。 为了澄清,我想将populateMonsterspopulateClassesTaken传递给create并能够在create内调用它们。

typedef struct node{
   void * data;
   struct node* next;
} node;

typedef struct MonsterAttacks{
    unsigned int attackID;
    char monsterName[41];
    char attackLocation[41];
    unsigned int numOfVictims;
}MonsterAttacks;

typedef struct ClassesTaken{
    unsigned int classID;
    char semester[41];
    unsigned int year;
    unsigned int numberOfUnits;
    char grade[10];
}ClassesTaken;


  unsigned int idM = 1;

  MonsterAttacks * populateMonsters(){

    MonsterAttacks *m = NULL;

    m->attackID = idM;
    printf("Enter the name for the Monster \n");
    scanf("%40s",m->monsterName);
    puts("What is his/her attack location?");
    scanf("%40s",m->attackLocation);
    puts("What are the number of victims this monster has demolished?");
    scanf("%ud", &m->numOfVictims);      
    //attackID is assigned and id when node is created
    idM++;
    return m;
}

  unsigned int idC = 1;

  ClassesTaken* populateClassesTaken(){

    ClassesTaken *c = NULL;
    c->classID = idC;
    scanf("What semester was the class taken in? %40s",c->semester);
    scanf("In what year? %ud", &c->year);  
    scanf("How many units was the class? %ud", &c->numberOfUnits);
    scanf("What was your grade in the class? %9s", c->grade);     


    idC++;
    return c;
}

node* create(node* next, void *fp)
{
   node* new_node = (node*)malloc(sizeof(node));
   if(new_node == NULL)
   {
       printf("Error creating a new node.\n");
       exit(0);
   }
    void *data = (*fp)();
}



int main(void)
{

   node* tmp = NULL;
   MonsterAttacks* (*fp)() = &populateMonsters;

   create(tmp, *fp);
}

首先,不用说您不能编写像ClassesTaken *c = NULL; c->classID = idC;这样的代码ClassesTaken *c = NULL; c->classID = idC; ClassesTaken *c = NULL; c->classID = idC; 如果您不明白为什么不能这样做,则需要重新学习指针的基本知识,如下所述:将数据复制/扫描/读取到未初始化的指针时发生崩溃或“分段错误”

至于不同的功能-它们不同的功能类型这一事实清楚地表明此设计没有意义。 如果希望使用通用函数指针,则需要定义统一的函数格式,例如void* func (void)

不能void*用作通用函数指针。 它仅定义为用于指向对象的指针,而不用于函数。 诸如create(tmp, *fp); 其中fp是函数指针,函数期望void*不是有效的标准C,并且不应编译,除非您使用的是非标准编译器扩展。

值得注意的是,在C语言中,绝对不要声明带空parenthis ()函数。这是一种过时的语言功能。 (与C ++不同,这很好并且值得鼓励。)

更换:

node* create(node* next, void *fp)
{

与:

node* create(node* next, void* (*fp)())
{

create(tmp, *fp);

create(tmp, (void*)fp); //[updated]

您的populateMonsters()导致分段错误。 我将其代码替换为fputs("In populateMonsters\\n", stderr);

它似乎起作用:

$ ./每年

在populateMonsters中

populateMonsters()populateClassesTaken()仍然存在问题。 您想用用户输入来填充结构,但您永远不要分配结构(既不在堆上也不在堆栈上)。 因此,您会遇到细分错误。 这是我没有typedef的代码,包括...

typedef void*(*myFunctionInterface)(void);

MonsterAttacks * populateMonsters (){

  MonsterAttacks *m = (MonsterAttacks*)malloc(sizeof(MonsterAttacks));
  if (m == NULL){
      printf("Error creating MonsterAttacks");
      exit (-1);
  }

  m->attackID = idM;
  printf ("Enter the name for the Monster \n");
  scanf ("%40s", m->monsterName);
  puts ("What is his/her attack location?");
  scanf ("%40s", m->attackLocation);
  puts ("What are the number of victims this monster has demolished?");
  scanf ("%ud", &m->numOfVictims);
  //attackID is assigned and id when node is created
  idM++;
  return m;
}

unsigned int idC = 1;

ClassesTaken * populateClassesTaken (){

  ClassesTaken *c = (ClassesTaken*)malloc(sizeof(ClassesTaken));
  if (c == NULL){
      printf("Error creating ClassesTaken");
      exit(-2);
  }
  c->classID = idC;
  scanf ("What semester was the class taken in? %40s", c->semester);
  scanf ("In what year? %ud", &c->year);
  scanf ("How many units was the class? %ud", &c->numberOfUnits);
  scanf ("What was your grade in the class? %9s", c->grade);


  idC++;
  return c;
}

node * create (node * next, void *(*fp) ()){
  node *new_node = (node *) malloc (sizeof (node));
  if (new_node == NULL)
    {
      printf ("Error creating a new node.\n");
      exit (-3);
    }
  void *data = fp();
  new_node->data = data;
  return new_node;
}



int main (void) {    
  node *tmp = NULL;
  MonsterAttacks *(*fp_M) () = &populateMonsters;
  ClassesTaken *(*fp_C) () = &populateClassesTaken;
  create (tmp, (myFunctionInterface)fp_M);
}

如果出现错误,则返回0也不是一个好的样式。 0通常表示一切正常。 因此,我将退出值更改为一些不同的负数以区分错误

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM