在C语言中,指针是一个很重要但是又很容易弄错的概念,也可以说指针就是C语言的灵魂,所以说学好指针对于完全掌握C语言是一个必须的过程。
指针函数
指针函数就是返回指针值的函数,本质是一个函数。所以指针函数等价于“返回值为指针的函数”。
声明形式:type *func (参数列表)
为了便于理解,再进一步描述一下。
看看下面这个函数声明:
int fun(int x,int y);
这种函数,其实就是一个函数,然后返回值是一个 int 类型,是一个数值。
接着看下面这个函数声明:
int *fun(int x,int y);
这和上面那个函数唯一的区别就是在函数名前面多了一个*号,而这个函数就是一个指针函数。其返回值是一个 int 类型的指针,是一个地址。
实例:
#include <iostream>
using namespace std;
int* getNum(int x); //指针函数声明形式
int main()
{
cout << "===start===" << endl;
int num;
cout << "please enter a num: " << endl;
cin >> num;
cout << "result is: " << *getNum(num) << endl; //输出返回地址中的值
}
int* getNum(int x)
{
static int num[] = {0,1,2,4,5};
return &num[x]; //返回一个地址
}
输出:
===start===
please enter a num:
3
result is: 4
函数指针
函数指针就是一个指向函数的指针。每个函数在编译时,会被分配一个入口地址,一般用函数名来表示,这个地址就是该函数的指针。
声明形式:type (*func)(参数列表 )
从上面的定义形式可以看出,函数指针和指针函数的直观上区别在于指针符号*与函数名/指针名有没有用括号()包裹起来,从这一点来看是很容易区分两者的。
函数指针是需要把一个函数的地址赋值给它,有两种写法:
func = &Function;
func = Function;
取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
调用函数指针的方式也有两种:
x = (*fun)();
x = fun();
两种方式均可,其中第二种看上去和普通的函数调用没啥区别,如果可以的话,建议使用第一种,因为可以清楚的指明这是通过指针的方式来调用函数。当然,也要看个人习惯,如果理解其定义,随便怎么用都行啦。
实例:
#include <iostream>
using namespace std;
int max(int a, int b)
{
return a > b ? a : b;
}
int main()
{
int (*func)(int, int);
func = max;
int a, b;
cout << "please input 2 numbers: " << endl;
cin >> a >> b;
cout << "max= " << (*func)(a, b) << endl; //使用指针变量调用函数
cout << "max= " << func(a, b) << endl; //使用函数指针名调用
cout << "max= " << max(a, b) << endl;
return 0;
}
输出:
please input 2 numbers:
3 4
max= 4
max= 4
max= 4
上例给出了函数指针的两种最普遍的调用形式,一个是直接用定义的指针变量(* func)调用,一个是用指针名调用,后者看起来就像是将原函数使用了新名称去调用一样,可以看成函数的别名。再次强调一下:指针变量名和指针符号 * 一定要用括号包裹起来。函数指针还有一种常用的使用方式,就是使用typedef定义后再使用。将上例稍作修改如下:
实例:
#include <iostream>
using namespace std;
int max(int a, int b)
{
return a > b ? a : b;
}
typedef int (*func)(int, int);
int main()
{
func maxfunc = max;
int a, b;
cout << "please input 2 numbers: " << endl;
cin >> a >> b;
cout << "max= " << (*maxfunc)(a, b) << endl; //使用指针变量调用函数
cout << "max= " << maxfunc(a, b) << endl; //使用函数指针名调用
cout << "max= " << max(a, b) << endl;
return 0;
}
输出:
please input 2 numbers:
2 4
max= 4
max= 4
max= 4
指针数组
指针数组可以说成是”指针的数组”,首先这个变量是一个数组,其次,”指针”修饰这个数组,意思是说这个数组的所有元素都是指针类型,在32位系统中,指针占四个字节。
声明形式:type *var[n]
如int p[n]
[]优先级高,先与p结合成为一个数组,再由int说明这是一个整型指针数组,它有n个指针类型的数组元素。
指针数组常用在主函数传参,在写主函数时,参数有两个,一个确定参数个数,一个这是指针数组用来接收每个参数(字符串)的地址
int main(int argc, char *argv[])
如果是向子函数传参,这和传递一个普通数组的思想一样,不能传递整个数组过去,如果数组很大,这样内存利用率很低,所以应该传递数组的首地址,用一个指针接收这个地址。因此,指针数组对应着二级指针
void fun(char **pp);//子函数中的形参
fun(char *p[]);//主函数中的实参
实例:
#include <stdio.h>
#include <string.h>
void sort(char** pa, int n)
{
int i, j;
char *tmp = NULL;
for(i = 0; i < n; i++) {
for(j = 0; j < n-i; j++) {
if((strcmp(*(pa+j), *(pa+j+1))) > 0) {
tmp = *(pa+j);
*(pa+j) = *(pa+j+1);
*(pa+j+1) = tmp;
}
}
printf("%s\n",*(pa+j));
}
}
int main()
{
char *pa[4] = {"abc", "def", "xyz", "def"};
sort(pa, 4);
return 0;
}
输出:
xyz
def
def
abc
数组指针
数组指针可以说成是”数组的指针”,首先这个变量是一个指针,其次,”数组”修饰这个指针,意思是说这个指针存放着一个数组的首地址,或者说这个指针指向一个数组的首地址。
声明形式:type (*var)[n]
如int (*p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。
实例:
#include <stdio.h>
void fun(int (*a)[4], int m, int n) {
printf("%d\n", *(*(a+m)+n));
printf("%d\n", *(*(a+m)+n+1));
printf("%d\n", *(*(a+m+1)+n));
}
int main()
{
int a[3][4] = {{1,2,3,4},{4,3,2,1},{5,6,7,8}};
fun(a, 1, 1);
return 0;
}
输出:
3
2
6
函数指针数组
顾名思义,就是每个元素都是函数指针的数组,直接在函数指针名后面加上数组符号[ ]即可。
声明形式:type (*func[ ])(参数列表 )
实例:
#include <iostream>
using namespace std;
void fun1() {
cout << "fun1 is running" << endl;
}
void fun2() {
cout << "fun2 is running" << endl;
}
void fun3() {
cout << "fun3 is running" << endl;
}
int main()
{
//定义3个函数指针
void (*pfun1)() = &fun1;
void (*pfun2)() = &fun2;
void (*pfun3)() = &fun3;
//定义一个数组把它们装进去
void(*pfunarr[3])();
pfunarr[0] = pfun1;
pfunarr[1] = pfun2;
pfunarr[2] = pfun3;
/* pfunarr[0] = &fun1;
pfunarr[1] = &fun2;
pfunarr[2] = &fun3; */
//调用
pfunarr[0]();
pfunarr[1]();
pfunarr[2]();
/* //或者调用
(*pfunarr[0])();
(*pfunarr[1])();
(*pfunarr[2])(); */
return 0;
}
输出:
fun1 is running
fun2 is running
fun3 is running
指向函数指针数组的指针
声明形式:type (* (*func )[ ])(参数列表 )
实例:
#include <iostream>
using namespace std;
void fun1() {
cout << "fun1 is running" << endl;
}
void fun2() {
cout << "fun2 is running" << endl;
}
void fun3() {
cout << "fun3 is running" << endl;
}
int main()
{
void(*pfunarr[3])();
void(*(*pfunarr2)[3])();
pfunarr[0] = &fun1;
pfunarr[1] = &fun2;
pfunarr[2] = &fun3;
pfunarr2 = &pfunarr;
(*pfunarr2)[0]();
pfunarr[0]();
return 0;
}
输出:
fun1 is running
fun1 is running
分析其定义形式:void((pfunarr2)[3])()
其中( pfunarr2)[3]表示数组指针,而void( )( )表示函数指针,两者结合起来就是指向函数指针数组的指针。
https://blog.youkuaiyun.com/u010183728/article/details/80967283