一、函数指针
1、相关定义
函数指针 static
指针
就是一个地址
使用
基类型(当前这个指针变量说指向的变量的类型) * 指针变量名
指针变量(指向存放地址的变量):
单指针 双指针 指针数组 数组指针 指针函数 函数指针
单指针 – 可以和一个 变量、一维数组、二位数组、函数 联系
双指针 – 可以和一个 变量 、指针数组 联系
字符指针 –
2、右左法则
认指针的法则 – 右左法则 --往右看一个,在往左看一个,在看右边,只有往复,直到将其看完。
将得到的逐个往前补充;
示例:
int (*p)[4]
— 整型数组指针 – 指向数组的指针
先找这句话的标识符 - p,
先往右看,有小括号,先个*结合,说明p是个指针;
在往右看,是[ ,是个数组,所以为数组指针;
在往左看,是int,为整型,所以是整型数组指针。
int *q[4]
— 指针数组 – 存储指针的数组
先找标志符,这里为q,没有(),就先往右看,为[,所以是q是一个数组;
在往左看一个,为*,所以为指针数组;
在往右看,看完了,往左看,为int,所以是整型指针数组;
int (*p1[5])
— 指针数组
和q一样,
int *(*p2[3])(int)
**— 指针函数指针数组 – **
先找标志符,这里为p2,
先往右看,为[
,为数组,所以为数组;
在往左看,为*
,为指针,所以为指针数组;
再往右看,为(
,是函数,所以为函数指针数组;
再往坐看,为 *
,是指针,所以为指针函数指针数组;
再往右看,没了,往左看,为int,是整型,所以为整型指针函数指针数组。
int *p3(int n)
— 指针函数 – 返回值为指针的函数
先找标志符,这里为p3,
先右看,为(
,是函数,所以为函数;
再往左看,为*
,是指针,所以是指针函数;
再往右看,没了,往左看,为int
,是整型,所以是整型指针函数。
int (*p4)(int ,int )
— 函数指针 – 指向函数的指针
先找标志符,这里为p4,
先往右看,为)
,是小括号,先看括号内,为*
,是指针,所以是指针;
再往右看,为(
,是函数,所以为指针函数;
再往左看,为int
,是整型,所以为整型指针函数。
3、函数指针的用法
1)基础应用:函数名 – 代表函数的入口地址
int Sum(int a,int b)
{
return a + b;
}
void main()
{
int (*p)(int ,int );//p是一个指针,指向一类函数,函数有两个int型参数,返回值为int
p = Sum;
cout << Sum(4,7) << endl;
cout << p(3,4) << endl;
}
运行结果:
对于int (*p)(int ,int );
的看理解:p是一个指针,指向一类函数,函数有两个int型参数,返回值为int
2)指针指向函数,由指针调用函数
代码示例:
int max(int a,int b)
{
return a > b ? a : b;
}
int min(int a,int b)
{
return a < b ? a : b;
}
void test(int x,int y,int (*p)(int,int))
{
cout << "test :" << p(x,y) << endl;//max(2,9)
}
void main()
{
//函数指针作为另外一个函数的参数
test(2,9,max);//将max传给p,相当于p = max
}
运行结果:
3)函数指针作为另外一个函数的参数
代码示例:
int min(int a,int b)
{
return a < b ? a : b;
}
//函数指针作为另外一个函数的返回值
/*
函数指针函数 -- fn是个函数名,函数里面有int n的一个参数,fn函数的返回值是个指针,这个指针指向一类函数 - int xx(int,int)
*/
int (*fn(int n))(int ,int )//函数指针函数
{
cout << "fn n = " << n << endl;
return min; //返回值是个指向函数的指针,在此可以返回函数名
}
void main()
{
cout << "函数指针作为函数返回值 " << endl;
cout << fn(100)(3,20) << endl; //先调用fn函数,将100传递给参数n,fn函数返回min,再掉用min(3,20)
//等价于
//int (*p)(int ,int );
//p = fn(100); //p = min
//cout << p(3,20) <<endl;
}
运行结果:
4)函数指针作为另外一个函数的返回值
函数指针数组
int Sum(int a,int b)
{
return a + b;
}
int max(int a,int b)
{
return a > b ? a : b;
}
int min(int a,int b)
{
return a < b ? a : b;
}
int Sub(int a,int b)
{
return a - b;
}
int Mul(int a,int b)
{
return a*b;
}
int Div(int a,int b)
{
return a*b;
}
int Mod(int a,int b)
{
return a%b;
}
//将同一类型的函数放一起 类似于函数数组 -- 函数指针
int main()
{
int (*p[])(int,int) = {Sum,max,min,Sub,Div,Mul,Mod}; //函数指针数组
int x = 10,y = 20;
int n = sizeof(p)/sizeof(p[0]);
for(int i = 0;i < n; i++)
{
cout << p[i](x,y) << endl;
}
}
5)扩展 – 函数转移表 *** 最重要
整体测试代码
#if 0
int Sum(int a,int b)
{
return a + b;
}
#if 1
int max(int a,int b)
{
return a > b ? a : b;
}
int min(int a,int b)
{
return a < b ? a : b;
}
void test(int x,int y,int (*p)(int,int))
{
cout << "test :" << p(x,y) << endl;//max(2,9)
}
#endif
//3、函数指针作为另外一个函数的返回值
#if 0
/*
函数指针函数 -- fn是个函数名,函数里面有int n的一个参数,fn函数的返回值是个指针,这个指针指向一类函数 - int xx(int,int)
*/
int (*fn(int n))(int ,int )//函数指针函数
{
cout << "fn n = " << endl;
return min; //返回值是个指向函数的指针,在此可以返回函数名
}
#endif
#if 0
int Sub(int a,int b)
{
return a - b;
}
int Mul(int a,int b)
{
return a*b;
}
int Div(int a,int b)
{
return a*b;
}
int Mod(int a,int b)
{
return a%b;
}
#endif
//将同一类型的函数放一起 类似于函数数组 -- 函数指针
#if 0
int main()
{
int (*p[])(int,int) = {Sum,max,min,Sub,Div,Mul,Mod}; //函数指针数组
int x = 10,y = 20;
int a = sizeif(p)/sizeof(p[0]);
for(int i = 0;i < n; i++)
{
cout << p[i](x,y) << endl;
}
}
#endif
#if 1
void main()
{
//2、函数指针作为另外一个函数的参数
test(2,9,max);//将max传给p,相当于p = max
//3
//cout << "函数指针作为函数返回值 " << endl;
//cout << fn(100)(3,20) << endl; //先调用fn函数,将100传递给参数n,fn函数返回min,再掉用min(3,20)
//p = fn(100);
//cout << p(3,20) <<endl;
}
#endif
#endif
二、相关笔试题
1、指针和字符串的相关笔试题
代码
void main()
{
char a[] = "123";
char b[] = "123";
const char c[] = "123";
const char d[] = "123";
const char* p1 = "123";
const char* p2 = "123";
const char* const p3 = "123";
const char* const p4 = "123";
//char* p5 = "123";//对于高级编译器不能通过,会报错 ,只是指向,不能改变
if(a == b)
cout << "a == b" << endl;
if(a == c)
cout << "a == c" << endl;
if(c == d)
cout << "c == d" << endl;
if(p1 == p2)
cout << "p1 == p2" << endl;
if(p3 == p4)
cout << "p3 == p4" << endl;
if(p1 == p3)
cout << "p1 == p3" << endl;
}
理解:
对于代码char a[] = "123";
来说,其实是定义了一个数组a,给a数组开辟了4个字节的空间,给四个字节里存放了1 2 3 \0。
b数组同理。
a、b数组名代表的是数组的首元素的首地址。
所以两者不相同。
对于const char* p1 = "123";
来说,p是个指针型变量,并没有开辟空间,p指向了一个字符串常量区的字符串常量,p里面存储的是其所指向的字符串常量的首地址,并没有开辟空间。只是指向,不能修改。
所以两者相同。
运行结果:
2、函数指针相关笔试题
1+2++3+…+n 要求,不能用if,不能用循环,不能用公式,不能直接输出结果
int f0(int n)
{
return 0;
}
int f1(int n)
{
static int (*pf[2])(int) = { f0,f1 }; //pf[0] = f0 fp[1] = f1
return pf[!!n](n - 1) + n;
}
void main()
{
cout << f1(100) << endl;
}
运行结果:
理解:
static int (*pf[2])(int) = { f0,f1 }; //pf[0] = f0 fp[1] = f1
定义了一个静态的函数指针数组,只在第一次调用的时候开辟空间,后面不会再开辟。
pf它是个数组,里面存的是指针,指针指向的返回值为int,里面有一个int类型的这类函数;相当于 pf[0]指向f0,pf[1]指向f1
return pf[!!n](n - 1) + n;
其中!!n
,如果其中的值为99,先取反为0,再取反为1.
程序运行的大体流程:
n = 100
return pf[!!100](99)+100->return pf[1](99)+100--->f1(99)+100
n = 99
return pf[!!99](98)+99 ---- f1(98)+99
n = 98
return pf[!!98](97)+98 -----f1(97)+98
......
n = 0
return pf[!!0](-1)+0 -----pf[0](-1)+0-----f0(-1)+0---0
3、二运算符重载相关试题:
class Magic
{
double x;
public:
Magic(double d = 0.00):x(fabs(d)){}
Magic_____{return Magic(sqrt(x*x + c.x*c.x));}
_____<<(ostream & os,Mgic c){return os<<c.x;}
};
void main()
{
Magic ma;
cout<<ma<<","<<Magic(-8)<<","<<ma+Magic(-3)+Magic(-4);
}
operator+(Magic c)
friend ostream& operator
代码:
#include <math.h>
class Magic
{
double x;
public:
Magic(double d = 0.00):x(fabs(d)){}
Magic operator+(Magic c)//Magic(-3) 是一个无名对象,所以参数未Magic c
{
return Magic(sqrt(x*x + c.x*c.x));
}
friend ostream& operator<<(ostream & os,Magic c);
};
ostream& operator<<(ostream &os,Magic c)
{
return os << c.x;
}
void main()
{
Magic ma;
cout << ma << ","<< Magic(-8) << "," << ma + Magic(-3) + Magic(-4);
}
运行结果:
4、桶排
n个1~10的数据,例如1 3 2 5 4 7 6 8 9 10 4 3 1 2 4 5 6 8 7 1 2 3 9 8 6
计算1~10出现的次数 — 票据的缺失 – 思想一样
void main()
{
int num[] = { 1,2,4,3,2,5,6,7,8,9,10,9,8,6,7,8,9,1,2,3,4,5,6,7 };
int n = sizeof(num) / sizeof(num[0]);
int count[11] = { 0 };
int i;
for (i = 0; i < n; i++)
{
count[num[i]]++;
/*
if(num[i] == 1)
count[1]++;
*/
}
for (i = 1; i <= 10; i++)
cout << i << " : " << count[i] << endl;
}