指向C中的函数说明

时间:2011-06-08 07:38:10

标签: c function-pointers

我不太明白这个目的。我已经搜索并阅读了不同来源的相同内容,但没有一个解释具体是什么以及它的目的是什么。

任何人都可以帮助我理解这个

5 个答案:

答案 0 :(得分:3)

让我们来看看标准C库:

void qsort(void *BASE, size_t NMEMB, size_t SIZE, 
    int (*COMPAR)(const void *, const void *) );

qsort的最后一个参数是指向比较函数的指针 compare 函数用于比较数组中的两个元素(它定义了排序)。 如果qsort()不使用函数指针,如果我们有不同的排序要求或新的类型/结构,我们将不得不一遍又一遍地写qsort()我们想排序。

答案 1 :(得分:3)

采取以下措施:

int i = 10;

可以像这样定义相应的指针:

int* p = &i;

变量“p”与“i”非常相似,因为它们都是数字。但是,'p'的值是变量'i'的存储器地址,换句话说,它是存储值10的确切存储器地址。此外,'p'知道该存储器地址的值的类型。它知道它是一个“int”,因为它被定义为“int”+“star”。

同样,考虑一个函数:

int m(char* arg1, double arg2)
{
    /* do something */
}

C提供了访问存储此函数的存储器地址的功能。函数不像一个值,例如它不能改变,所以当一个人说出一个函数的存储器地址时,这实际上意味着函数代码所在的存储器地址,例如,无论是花括号之间写的是什么。

然而,函数和变量之间存在相似性。他们都有一个类型。函数的类型包括:

  1. 返回类型
  2. 参数类型列表,即:
    1. 参数类型#1
    2. 参数类型#2
    3. ...
    4. 参数类型#N
  3. C将具有相同返回类型和参数类型列表的所有函数视为“相同类型的函数”。类似于声明为“int i,j”的两个变量被认为是相同的类型,具有相同签名的两个函数也被认为是相同的类型。

    描述函数类型的语法包括最小值:返回类型和每个参数的类型(按正确的顺序):

    return-type (* <variable-name>)(Type-of-Param-1, Type-of-Param-2, ..., Type-of-Param-N)
    

    实际上,为了在上面声明一个指向函数'm'的指针:

    int (*p)(char*, double) = &m;
    

    “int”是方法'm'的返回类型,圆括号的fir对和星号是语法的一部分,'p'是变量名,“char *”是第一个参数的类型,“double”是第二个参数的tyep。没有引用参数名称 - 因为参数的名称与函数的类型/签名无关。

    请注意,与变量类似,方法的地址与变量的地址完全相同,即前缀为&符号。

    指向函数的指针可以传递给simlar指向变量的指针,更重要的是,可以调用该特定内存地址的函数代码。例如,为了通过指针'p'调用函数'm',它将采用以下内容:

    int result = p(NULL, 10.0);
    int result = (*p) (NULL, 10.0); // alternative syntax
    

答案 2 :(得分:2)

典型的例子是一个排序函数,需要你将它“指向”一个可以比较两个元素的函数。您将此函数传递给比较函数的指针,以便在需要进行比较时调用函数。你实际上无法传递函数,但你可以传递一个指向函数的指针,该函数只是一个“指向”函数在内存中的位置的变量。排序函数可以使用此指针调用您的函数。通常,指针只是存储内存地址的变量。该内存地址是它“指向”的内容,它可以是该地址的任何内容 - 一个函数,一个整数,一系列以空字符结尾的字符变量。函数指针只是存储函数在内存中的内存地址的变量,因此该函数可以被其他一些代码调用。

希望解释有所帮助。

答案 3 :(得分:0)

这并不简单。

当您知道指针如何以及为什么使用常规变量时,请考虑使用这些指针,但这次使用函数。也就是说,你现在用函数的地址替换变量的地址,指针的所有功能,你现在可以通过使用指向它们的指针间接访问函数,而不是直接使用它们的名称。

来自http://www.cplusplus.com/doc/tutorial/pointers/

// my first pointer
#include <iostream>
using namespace std;

int main ()
{
  int firstvalue, secondvalue;
  int * mypointer;

  mypointer = &firstvalue;
  *mypointer = 10;
  mypointer = &secondvalue;
  *mypointer = 20;
  cout << "firstvalue is " << firstvalue << endl;
  cout << "secondvalue is " << secondvalue << endl;
  return 0;
}

上面的输出是

firstvalue is 10
secondvalue is 20

现在来自http://www.newty.de/fpt/intro.html#what 我们有函数指针。

//------------------------------------------------------------------------------------
// 1.2 Introductory Example or How to Replace a Switch-Statement
// Task: Perform one of the four basic arithmetic operations specified by the
//       characters '+', '-', '*' or '/'.


// The four arithmetic operations ... one of these functions is selected
// at runtime with a swicth or a function pointer
float Plus    (float a, float b) { return a+b; }
float Minus   (float a, float b) { return a-b; }
float Multiply(float a, float b) { return a*b; }
float Divide  (float a, float b) { return a/b; }


// Solution with a switch-statement - <opCode> specifies which operation to execute
void Switch(float a, float b, char opCode)
{
   float result;

   // execute operation
   switch(opCode)
   {
      case '+' : result = Plus     (a, b); break;
      case '-' : result = Minus    (a, b); break;
      case '*' : result = Multiply (a, b); break;
      case '/' : result = Divide   (a, b); break;
   }

   cout << "Switch: 2+5=" << result << endl;         // display result
}


// Solution with a function pointer - <pt2Func> is a function pointer and points to
// a function which takes two floats and returns a float. The function pointer
// "specifies" which operation shall be executed.
void Switch_With_Function_Pointer(float a, float b, float (*pt2Func)(float, float))
{
   float result = pt2Func(a, b);    // call using function pointer

   cout << "Switch replaced by function pointer: 2-5=";  // display result
   cout << result << endl;
}


// Execute example code
void Replace_A_Switch()
{
   cout << endl << "Executing function 'Replace_A_Switch'" << endl;

   Switch(2, 5, /* '+' specifies function 'Plus' to be executed */ '+');
   Switch_With_Function_Pointer(2, 5, /* pointer to function 'Minus' */ &Minus);
}

正如您将从上面的调用中看到的那样,Minus()函数的地址被传递,然后传递给它以通过指针调用实际函数,在本例中为pt2Func(...)。 请注意,在函数指针的情况下,您也将处理函数签名。

  • float (*pt2Func)(float, float)
  • float Minus (float a, float b) { return a-b; }

如上所示,签名是相同的,因此您可以传入任何函数地址,并且调用将起作用。

我希望这会有所帮助。

答案 4 :(得分:0)

函数指针用于动态调用函数。例如,您可以将函数指针作为另一个函数的参数,并在某种意义上以这种方式提供其他功能。您还可以创建具有函数指针的结构,从而创建一些成员函数,例如类。如果你有一个适用于你的结构的函数,这可能是有用的,但它们在实际应该用它们做什么工作上可能有点不同。例如:

// Structures for our "objects"
typedef int funcPtr();

struct foo {
  int a;
  int b;
  funcPtr* run;
}

struct bar {
  int a;
  int b;
  funcPtr* run;
  char* s;
}

// Functions that we will use as our "member functions"
int runOne() {
  return 1;
}

int runTwo() {
  return 2;
}

// Functions to create objects... kinda like new operators
struct foo* NewFoo(int aVal, int bVal) {
  struct foo* this = (stuct foo*)malloc(sizeof(struct foo));
  this->a = aVal;
  this->b = bVal;
  this->run = runOne;
  return this;
}

struct bar* NewBar(int aVal, int bVal) {
  struct bar* this = (stuct bar*)malloc(sizeof(struct bar));
  this->a = aVal;
  this->b = bVal;
  this->run = runTwo;
  return this;
}

// Create "objects"
struct foo* myFoo = NewFoo(10, 20);
struct bar* myBar = NewBar(30, 40);

// Run the run function on them (which actually runs different functions for each "object")
int result1 = myFoo->run();
int result2 = myBar->run();

result1 现在 1 result2 2 。如果您的结构包含具有相似接口但具有不同行为的不同类型的“模块”,则可以使用此方法。