int a, b = 0;
int* ip = &a;
int** sp = &ip;
int ar[10] = {
};
ip = ar;
int(*par)[10] = &ar;
int* pbr[10] = {
};
int* (*sbr)[10] = &pbr;
//需要定义一个指向一维整型数组的指针,才能指向pbr数组
//int fun(int, int); //= nullptr错误//函数声明
int (*pfun)(int, int) = nullptr;//函数指针变量的定义
int x = 10;
int y = 20;
int z = 0;
pfun = Add_Int;
z = Add_Int(x, y);
z = pfun(x, y);//新的函数调用规则
z = (*pfun)(x, y);//旧有的函数调用规则
pfun = Sub_Int;
z = pfun(x, y);
注意对于函数指针不能计算所指函数的大小,可以计算指针大小
sizeof(pfun);//√
//sizeof(*pfun);//x
函数指针可以作为函数的参数传到函数中
int Add_Int(int a, int b) {
return a + b;
}
int Sub_Int(int a, int b) {
return a - b;
}
void fun(int a, int b, int(*pfun)(int, int)) {
assert(pfun != nullptr);
int c = pfun(a, b);
printf("%d\n", c);
}
int main() {
fun(x, y, Add_Int);
fun(x, y, Sub_Int);
}
函数指针在作为函数参数的时候,可以采用函数声明的方式作为形参,这是一个比较特殊的点,比如下面两个函数参数中函数指针的写法是等价的,虽然这里面的int pfun(int, int)
是函数声明,但是确实正确的允许的
void fun(int a, int b, int pfun(int, int)) {
assert(pfun != nullptr);
int c = pfun(a, b);
printf("%d\n", c);
}
void fun(int a, int b, int(*pfun)(int, int)) {
assert(pfun != nullptr);
int c = pfun(a, b);
printf("%d\n", c);
}
void* Print_Int(void* p)
{
int* ip = (int*)p;
printf("%d ", *ip);
return ip + 1;
}
void* Print_Double(void* p)
{
double* dp = (double*)p;
printf("%lf ", *dp);
return dp + 1;
}
void* Print_Char(void* p)
{
char* cp = (char*)p;
printf("%c ", *cp);
return cp + 1;
}
void Print_Array(void* br, int n, void * (*fp) (void *) )
{
for (int i = 0; i < n; ++i)
{
br = (*fp)(br);
}
printf("\n");
}
int main()
{
int ar[] = {
12,23,34,45,56,67,78 };
int in = sizeof(ar) / sizeof(ar[0]);
double dx[] = {
1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9 };
int dn = sizeof(dx) / sizeof(dx[0]);
char str[] = {
"yhpinghello" };
char cn = strlen(str);
Print_Array(ar, in,Print_Int);
Print_Array(dx, dn,Print_Double);
Print_Array(str, cn, Print_Char);
return 0;
}
打印数组,数组类型不同,这个时候可以定义几个不同函数类型的函数,然后在打印数组的函数内传递函数指针参数,使得数组顺利打印出来,这里面就是函数回调的应用,是函数指针泛型函数的应用。
函数指针也可以作为函数返回类型来使用,如下面这段代码,但是由于函数指针如果作为函数返回类型来使用的话,会十分复杂,让人眼花缭乱,所以这里面采用typedef定义函数指针类型,方便了函数指针作为返回类型来使用
typedef int(*PFUN)(int, int);
//typedef int (*)(int, int) SFUN;//error
int (*g_fun)(int, int) = nullptr;
//int(*GetPFun(int (*fp)(int, int)))(int, int)
PFUN GetPFun(PFUN fp)
{
int (*old)(int, int) = g_fun;
g_fun = fp;
return old;
}
输入数字1-7,打印其对应的星期数
void PrintMon() {
printf("Monday\n"); }
void PrintTue() {
printf("Tuesday\n"); }
void PrintWed() {
printf("Wednesday\n"); }
void PrintThu(){
printf("Thursday\n"); }
void PrintFri() {
printf("Friday\n"); }
void PrintSat() {
printf("Saturday\n");}
void PrintSun(){
printf("Sunday\n"); }
void (*pfun[])() = {
PrintMon,
PrintTue,
PrintWed,
PrintThu,
PrintFri,
PrintSat,
PrintSun
};
void Print(int i)
{
assert(i >= 1 && i <= 7);
(*pfun[i - 1])(); //pfun[i - 1]();
}
int main()
{
int message;
while (scanf_s("%d", &message), message != -1)
{
Print(message);
}
return 0;
}
在vc 6.0++中有下面这个有意思的情况,可以根据函数指针地址,将其强转为函数对象,然后解引用调用该函数,也能调用成功。如下面这段代码:
void fun()
{
printf("yhping hello \n");
}
int main()
{
int a = 10;
void (*pfun)() = NULL;
pfun = (void (*)())0x0040b760;
(*pfun)();
(*((void (*)())0x0040b760))();
(*(void(*)())0))();
return 0;
}