字符指针
对于字符指针来说,尤其需要注意的地方就是:对于常量字符串,其内容是不可修改的。例:
char* p = “ abcdefg ";
*p = ' w ';
对于该代码,我们知道指针p代表的是首元素地址,也就是a的地址,解引用就可以拿到a这个字符,之后再进行修改。 这一切看似很正常,但也是比较坑的地方,就是:这里的abcdefg是常量字符串,本来就是不可修改的,值得注意!
指针数组
对于指针数组,也比较好理解,就是一个数组里面全部装的都是同类型的地址(指针),这里直接上代码:
int arr1[] = {1,3,4,6,9};
int arr2[] = {3,4,6,8,9};
int arr3[] = {3,5,2,5,7};
int* p[] = {arr1, arr2, arr3};
指针数组的概念和这块代码都比较简单,这里就不多加赘述。
数组指针
数组指针和指针数组都比较好理解,一个是指针,一个是数组,它们的概念也比较好懂。但是这里我比较想说的是它们的写法,这里写代码块来进行比较:
int* p[];
int (*p)[];
能看见两种写法有很大的不同:前面的p和[]结合,它就是个数组,然后再去掉p[],剩下的就是它的类型,发现是int*,所以它就是一个装满int*的指针数组;同样的道理,后面的p先和*相结合(因为打了括号,所以优先级高),它是个指针, 去掉*p,剩下的是它的类型int [],说明它的类型是装满int数据的数组,所以p是一个数组指针。
函数指针
顾名思义,函数指针就是存放函数的地址,它的形式较前面说的指针数组和数组指针有很大的区别,一眼就能看出来:
int Add(int a , int b)
{
return a+b;
}
int (*p)(int , int) = Add;
同样的道理,因为*和p先结合,那么它一定是一个指针。去掉*p来看,剩下的就是类型,是不是和函数很相似呢?(int, int)是函数形参,和申明函数和定义函数不同的是,这里可以省略变量的名字,只需要指定变量的类型;同理,前面的int就是函数的返回类型。
但是,我觉得这些都不是最重要的,最重要的是:函数名即地址!这一点跟数组有很大的区别,我们知道数组名只是代表首元素地址,而&数组名拿到的是整个数组的地址,虽然两者在表现上都是首个元素的地址,但是解引用时,前者拿到的是数组第一个元素,后者拿到的是整个数组,而且指针加1时,前者跳过首个元素指向第二个元素的地址,而后者跳过整个数组,拿到的是数组最后一个元素后面的那个地址。
那么重点来了,对于函数名来说,取不取地址拿到的都是该函数的地址,因为函数可没有首元素这一说,所以在创建一个函数指针时,可以是让该指针直接指向函数名或者&函数名。同样的道理,对该指针解不解引用都可以直接当作函数用,直接带入实参就完了。
函数指针数组
了解前面的几个指针后,依葫芦画瓢,函数指针也就比较容易理解了 ,我们直接来看其形式:
假设我们有加减乘除四个函数分别为Add、Sub、Mul、Div
int (*p[4])(int,int) = {Add, Sub, Mul, Div};
这里的分析方法和上面一样,大家可以尝试着自己拆解记忆哦!这里我在gitee里面上传了一段编写计算机的代码,主要是根据老师课堂上面所讲知识的一个总结,当然,代码都是老师课堂上面所讲的,我只是自己复刻一遍,也帮助自己记忆,希望也能帮到大家!
[基于函数指针数组开发的计算器](https://gitee.com/qj-xnjd/elementary-level-of-c-language.git)
补充
其实课堂老师还补充了指向函数指针数组的指针,指向函数指针数组的指针数组等等,无限套娃。虽然名字很长,但是套路都是一样的,而且这些也不怎么能要到了,所以只做了解。
最后,第一次写博客,希望大家看过后多多指正、多多建议!