1.字符指针
字符指针的常见形式是
int main()
{
char a='e'
char* b=&a;
return 0;
}
第二种是以字符串的形式
int main()
{
cahr* a="ahbhhfjsajkl";
return 0;
}
这种形式是将字符串的值属性就是首字母的地址赋给指针a,字符串的类型属性是char *(表达式都有值属性和类型属性),上面的字符串是常量字符串是具有常量属性,不能修改,最好在char*前面加上const,防止更改,常量字符串在内存存储时在只读数据区,通常只创建一个,如果两个指针指向一个字符串就会是同一个地址 ,如图
2.数组指针
数组指针就是将地址集合成一个数组
如下形式
int main()
{
int a = 0;
int b = 9;
int c = 8;
int* arr[3] = { &a,&b,&c };
return 0;
}
3.数组指针
数组指针是存储整个数组的地址,数组名取地址得到的就是整个数组的地址,数组指针的格式是
int arr[10]={1,2,3,4,5,6,7,8,9,0};
int (*p)[10]=&a;
数组指针的数据类型是int (*)[10],int代表数组指针的类型就是数组指针指向的数组的元素数据类型,*代表是指针,[10]代表的指向的数组的元素个数。数组指针的步长是整个数组。
数组指针在解引用时相当于arr,也就是首元素的地址。
在上面图中在数组传参时,接收时使用int (*p)[5],是因为二维数组中数组名代表第一行的地址,相当于一个一维数组因此使用 数组指针进行接收。
由于int (*p)[5]数据类型在内存中占用20个字节,所以p+1跳过的是40个字节的地址。下面两个地址相差20 个字节。
还有一种数组指针数组,他是数组指针的集合,例如:int (*p[5])[7],这个int(*)[7]是数据类型,后面7是代表数组的元素个数。
4.函数指针
函数指针就是存储函数地址的指针,函数名和取地址函数是相同的效果函数指针形式基本和数组指针相同,如下
void (*pg) (int ,int)=&add;
void (*pf) (int ,int)=add;
数据类型是void(*)(int,int)有点类似函数声明,只要写出函数参数类型,void是函数返回类型,(*)代表都是指针,(int,int)是函数参数类型。
函数指针的使用可以解引用和不解引用(类似于函数名直接使用方法)就是基本相同函数传参。
void (*pg) (int ,int)=&add;
void (*pf) (int ,int)=add;
*pf(9,6);
pg(3,4);
函数指针指针的应用主要是在多个函数调用更加灵活增加调用时的灵活性和简便性,如下函数中
5.函数指针数组和指向函数指针数组的指针
函数指针数组类似于数组指针数组,就是存放函数指针的数组,也是简化了调用时的复杂程度,对于上图来说,函数指针数组可以去掉switch的选项改成int (*p[3])(int,int)={0,add,chu}就可以根据输入数据来调用数组从而实现简化。上面int (*)(int,int)是指针类型,p是指针名,[]代表数组元素个数。
指向函数指针数组的指针就是存放函数指针数组的指针格式为
int (*p)(int,int)=test;
int(*p[5])(int,int);
int(*(*p)[5])(int,int);
一定要强调的是指针类型是int(*)(int,int)
里面的(*p)[5]就是指针数组的形式,我们可以写成类型_(*p)[5]更加容易理解。