2011-06-08 23 views
1

我不太明白这个的目的。我已经搜索并阅读了不同来源上似乎相同的东西,但没有一个解释它具体是什么,它的目的是什么。指针函数C中的函数说明

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

+1

谁提出这样的问题? – cnicutar 2011-06-08 08:04:39

+0

你基本上在事先不知道你想要调用的函数时使用函数指针。 – pmg 2011-06-08 08:17:12

回答

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); 
} 

,你从上面的调用,减号()函数的传递是然后传递通过指针,在这种情况下,pt2Func(...)来调用实际函数的地址看看。 请注意,在函数指针的情况下,您也将负责函数签名。

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

正如你可以在上面看到,签名是相同的,所以你可以在任何函数地址传递,呼叫会工作。

我希望这会有所帮助。

+1

发布时请学会格式化代码 – 2011-06-08 07:50:15

+0

@Paul,它不是我的错,所以没有显示格式化按钮或我的浏览器变坏了! – 2011-06-08 07:52:09

+0

您可以通过手动缩进来格式化。 – 2011-06-08 07:53:25

3

让我们在标准C库看看:

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

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

+1

基本上,Op的例子显示函数指针允许函数作为参数传递。 – 2011-06-08 07:49:10

2

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

希望解释有帮助。

+0

这个例子显示函数指针允许函数作为参数传递给其他函数,这是很好的例子。 – 2011-06-08 07:50:35

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现在将和RESULT2将。如果您的结构包含不同类型的“模块”,并且具有类似的界面但具有不同的行为,则可以使用这种方法。

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. 的参数#类型的参数#2
    2. 类型.. 。
    3. 参数类型#N

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”,杉对圆形托架和所述星号的语法的一部分的返回类型,“p”为变量名, “char *”是第一个参数的类型,“double”是第二个参数的tyep。没有引用参数名称 - 因为参数的名称与函数的类型/签名无关。

请注意,类似于变量,方法的地址与变量的地址完全相同,即通过将其前置为&符号。

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

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