C语言入门之函数指针
像正常的数据指针(int *,char *等),我们可以有函数指针。 下面是一个简单的例子,显示使用函数指针的声明和函数调用。#include <stdio.h>
// A normal function with an int parameter
// and void return type
void fun(int a)
{
printf("Value of a is %d\n", a);
}
int main()
{
// fun_ptr is a pointer to function fun()
void (*fun_ptr)(int) = &fun;
/* The above line is equivalent of following two
void (*fun_ptr)(int);
fun_ptr = &fun;
*/
// Invoking fun() using fun_ptr
(*fun_ptr)(10);
return 0;
}输出:Value of a is 10为什么我们需要在上面的例子中像fun_ptr这样的函数指针加一个括号?如果我们删除括号,则表达式
void (*fun_ptr)(int)变成void * fun_ptr(int)它是一个返回void指针的函数的声明。 有关详细信息,请参阅以下帖子。
如何声明一个指向一个函数的指针?
以下是一些有关函数指针的有趣事实。
[*]与正常指针不同,函数指针指向代码,而不是数据。 通常,函数指针存储可执行代码的开始地址。
[*]与正常指针不同,我们不使用函数指针去分配内存。
[*]函数名也可用于获取函数地址。例如,在下面的程序中,我们已删除地址运算符'&'。我们也通过删除*改变了函数调用,程序仍然工作。
#include <stdio.h>
// A normal function with an int parameter
// and void return type
void fun(int a)
{
printf("Value of a is %d\n", a);
}
int main()
{
void (*fun_ptr)(int) = fun;// & removed
fun_ptr(10);// * removed
return 0;
}输出:Value of a is 10
[*]像普通指针一样,我们可以有一个函数指针数组。
[*]函数指针可用于switch case。例如,在下面的程序中,用户被要求在0到2之间选择做不同的任务。
#include <stdio.h>
void add(int a, int b)
{
printf("Addition is %d\n", a+b);
}
void subtract(int a, int b)
{
printf("Subtraction is %d\n", a-b);
}
void multiply(int a, int b)
{
printf("Multiplication is %d\n", a*b);
}
int main()
{
// fun_ptr_arr is an array of function pointers
void (*fun_ptr_arr[])(int, int) = {add, subtract, multiply};
unsigned int ch, a = 15, b = 10;
printf("Enter Choice: 0 for add, 1 for subtract and 2 "
"for multiply\n");
scanf("%d", &ch);
if (ch > 2) return 0;
(*fun_ptr_arr)(a, b);
return 0;
}
Enter Choice: 0 for add, 1 for subtract and 2 for multiply
2
Multiplication is 150
[*]像正常的数据指针一样,函数指针可以作为参数传递,也可以从函数中返回。例如,象下面的C程序,wrapper()接收到一个void fun()作为参数数
// A simple C program to show function pointers as parameter
#include <stdio.h>
// Two simple functions
void fun1() { printf("Fun1\n"); }
void fun2() { printf("Fun2\n"); }
// A function that receives a simple function
// as parameter and calls the function
void wrapper(void (*fun)())
{
fun();
}
int main()
{
wrapper(fun1);
wrapper(fun2);
return 0;
}这一点在C中特别有用,我们可以使用函数指针来避免代码冗余。
// An example for qsort and comparator
#include <stdio.h>
#include <stdlib.h>
// A sample comparator function that is used
// for sorting an integer array in ascending order.
// To sort any array for any other data type and/or
// criteria, all we need to do is write more compare
// functions.And we can use the same qsort()
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main ()
{
int arr[] = {10, 5, 15, 12, 90, 80};
int n = sizeof(arr)/sizeof(arr), i;
qsort (arr, n, sizeof(int), compare);
for (i=0; i<n; i++)
printf ("%d ", arr);
return 0;
}输出:5 10 12 15 80 90
象qsort()相似,我们可以编写自己的函数,可用于任何类型的数据,可以做不同的任务没有冗余代码
#include <stdio.h>
#include <stdbool.h>
// A compare function that is used for searching an integer
// array
bool compare (const void * a, const void * b)
{
return ( *(int*)a == *(int*)b );
}
// General purpose search() function that can be used
// for searching an element *x in an array arr[] of
// arr_size. Note that void pointers are used so that
// the function can be called by passing a pointer of
// any type.ele_size is size of an array element
int search(void *arr, int arr_size, int ele_size, void *x,
bool compare (const void * , const void *))
{
// Since char takes one byte, we can use char pointer
// for any type/ To get pointer arithmetic correct,
// we need to multiply index with size of an array
// element ele_size
char *ptr = (char *)arr;
int i;
for (i=0; i<arr_size; i++)
if (compare(ptr + i*ele_size, x))
return i;
// If element not found
return -1;
}
int main()
{
int arr[] = {2, 5, 7, 90, 70};
int n = sizeof(arr)/sizeof(arr);
int x = 7;
printf ("Returned index is %d ", search(arr, n,
sizeof(int), &x, compare));
return 0;
}输出:Returned index is 2
上述搜索函数可以通过编写单独的自定义compare()来用于任何数据类型。
参考:
http://www.cs.cmu.edu/%7Eab/15-123S11/AnnotatedNotes/Lecture14.pdfnote.youdao.com/]http://www.cs.cmu.edu/~ab/15-123S11/AnnotatedNotes/Lecture14.pdf
http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-087-practical-programming-in-c-january-iap-2010/lecture-notes/MIT6_087IAP10_lec08.pdf
http://www.cs.cmu.edu/~guna/15-123S11/Lectures/Lecture14.pdf
本文由Abhay Rathi提供。
听讲了。
C中的面向对象编程的关键,就是结构和函数指针。
来听课~~~
终于看懂了~~~
谢谢楼主~~~ 请教一下楼主
int fun(int *a)
{
return (*a)*(*a);
}
int main()
{
int v = 20;
int *p;
//第1种用法
fun( &v );
//第2种用法
p = &v;
fun( p );
//请问如果不声明任何变量的情况下,想用20的值传给fun,该如何强制转化呢?
return 0;
}
好贴,在构架数据结构的时候,我喜欢用结构和函数指针。 zhuisuoji 发表于 2017-4-8 05:51
请教一下楼主
在函数内定义个局部变量如何? xfdr 发表于 2017-4-8 15:42
在函数内定义个局部变量如何?
目的就是想看看如何直接强制转换~~~ zhuisuoji 发表于 2017-4-8 05:51
请教一下楼主
函数可以多定义一个参数变量 zhuisuoji 发表于 2017-4-8 16:18
目的就是想看看如何直接强制转换~~~
常数是没有地址的,因此你的问题无解。
变通方案1:采用const常量代替常数,const本质还是变量。
变通方案2:绝对定位,直接将参数硬编码,坑自己,坑读程序的家伙们。
比如:const int XXX[]__at(0x20000000)= {20}; // 伪代码,绝对定位
fun((int*)0x20000000); //调用 偶尔看到这种用法,解释的不错啊 学习,谢谢!!! 学习了,非常棒
页:
[1]