1.指针的理解及应用
要想学习指针的相关知识,就要知道计算机中的地址到底是什么回事。其实跟现实世界中的地址没什么区别,我们知道CPU在运行时要从内存中拿取数据,那么我要想准确找到我们需要的数据该怎么办?很简单,跟内存也编号,给每一个内存空间一个独一无二的编号,这样在需要时才能准确在内存中找到我们需要的数据,而这个编号就是地址,注意在计算机中是一个字节一个地址。
而有了地址就要有东西能够存储地址,这个东西就是指针。我们先看一下学习指针变量的创建,比如此时有一个int类型的变量,int a=10;当我们想用指针的方法来运用局部变量a时,首先要创建一个指针变量来存局部变量a的地址。例如,int *pa=&a;这样就把局部变量的地址存到指针变量pa中了,然后就可以通过指针对进行运用了。如下图。
指针变量要pa要接受int*类型的数据,所以我们要把局部变量a的地址取出,并存入指针变量pa中,而通过解引用操作符(*)我们就可以改变或调用局部变量a。这里我们通过地址就可以找到局部变量a,而a的地址是唯一的,当中只有a,所以可以认为地址就是指针,而指针变量是用来存放指针,也就是存放地址的。
那我们如何通过指针调用数组呢?
首先要理解数组名,在C语言中数组名就代表了数组首元素的地址,而不用加上&符号。 &符号就是取出地址的意思。但有两种情况下数组名不是数组首元素地址。
1.sizeof(数组名),这个时候 sizeof计算的是整个数组的内存大小,所以这里的数组名就是整个数组的地址。
2.&数组名,这里的数组名也是代表了整个数组的地址。
但整个数组的地址和数组首元素的地址这两个有什么区别要在后面进行叙述。
我们可以用循环来改变arr[i]中的i来调用数组,也可以用指针来调用数组。但我们看图上是先对指针依次加上【0,1,2,3,4】后再进行解引用就依次调用了数组里的内容。
首先知道在C语言中任何变量都是有大小的,那么一个指针变量大小是多少?在32为机器上,有32根地址总线,一个地址就是32个bite(比特)位,就是四个字节,所以在32位机器上一个指针变量的大小就是4个字节,以此类推在64位机器上一个指针变量就是8个字节。
而指针中存的是一个地址,对一个地址进行加减后为什么就可以依次调用数组了?
所以指针的类型也很重要,不同的指针类型有不同的作用。
指针类型的作用:
1决定了对指针解引用时的权限(可以使用几个字节的内容)
2决定了指针加减整数时要移动几个字节
所以这里指针变量接收数组arr的地址后就是指向1的,而随着循环的进行,指针加上0,1,2,3,4。就是指针向后移动0,4,8,12,16个字节,再对指针进行解引用操作后就是可以得到数组中的内容,这就是指针可以调用数组的原因。
上面就是指针的基础用法用法,接下来讲解指针数组。
2指针数组
通过名字我们可以猜测一下指针数组是指针还是数组。
答案揭晓,指针数组是数组,只不过这个数组中存的不再是int或者char类型的数据,而是指针。
图上就是指针数组的用法,指针数组和整形数组,字符数组基本一样,只不过数组中存的类型不同,要注意指针数组中只能存放相同类型的指针。
3数组指针
在学习了指针数组之后,我们再来看下数组指针,那么数组指针是数组还是指针?
很明显,数组指针是一个指针,而且根据名字可以猜测数组指针应该是一个指向数组的指针。
通过调试,我们可以看见&arr和指针pa的类型相同。那么就可以分析int(*pa)[4]的构成。
int应该是数组指针指向的数组中的元素类型,[4]是指数组指针指向的数组中的元素个数,而pa就是数组指针的变量名。那么如何用数组指针打印arr数组呢?
上图就是数组指针的用法。
在我的另外一篇文章《C语言扫雷游戏的实现》中,我创建扫雷游戏的界面时多次用到了二维数组,还有二维数组的传参。而在学习了数组指针的相关知识后,我们就可以用函数指针的知识来解释二维数组传参的本质了。
在《C语言扫雷游戏的实现》中,我在对二维数组传参时都是用类似下图的方式来进行传参的。
直接用一个二维数组来作为形参。那么如何用数组指针来进行这种操作呢?
可以看见,通过对数组指针的两次解引用就可以访问我们创建的arr数组,那么为什么能这样做呢?
我们可以知道,我创建了一个三行五列的二维数组,然后我又把它传给了test函数,而test函数的形参是一个数组指针,我用pa来接收我创建的函数,而这个二维数组可以看成由三个内部有五个元素的一维数组组成,而二维数组的数组名代表的是第一行一维数组的地址。而整个数组的地址进行加减操作时跳过的是整个数组,所以(pa+i)调整的是第几行,而对(pa+i)进行解引用操作后,就进入了该行一维数组,也就是指向了该行一维数组的首元素地址,再对这个地址进行加减操作后,就是调整该行一维数组的第几个元素,最后的解引用操作就可以知道确切的内容。这就是通过数组指针对二维数组传参的理解。
4.函数指针
函数指针顾名思义就是指向函数的指针。格式为int(*pa)(int,int)。
需要解释一点,函数名=&函数名=函数的地址。
以上就是我对指针的一些看法,如有错误请指出。