一 、什么是指针
计算上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数 据也会放回内存中,每个内存单元都有⼀个编号,有了这个内存单元的编 号,CPU就可以快速找到⼀个内存空间,在计算机中我们 把内存单元的编号也称为地址。C语⾔中给地址起 了新的名字叫:指针。
简单的说,指针其实就是地址。
二 、&(取地址操作符)和 *(解引用操作符)
#include <stdio.h>
void test(int (*p)[5], int r, int c)
{
int i = 0;
int j = 0;
for(i=0; i<r; i++)
{
for(j=0; j<c; j++)
{
printf("%d ", *(*(p+i)+j));
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {{1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7}};
test(arr, 3, 5);
return 0;
}
当我们想通过地址来调用一个参数时,比如:
对于解引用操作符,可以用一个例子来理解:
*pa 的意思就是通过pa中存放的地址,找到指向的空间, *pa其实就是a变量了;所以*pa=0,这个操作符是把a改成了0. 其实这⾥是把a的修改交给了pa来操作,这样对a的修改,就多了⼀种的途径。
再比如,当我们想交换两个数a和b的值时,一般我们会选择创建一个临时变量c来实现交换,在有了指针的知识后我们可以选择对他们的地址进行处理:
这种函数调用方式叫做:传值调用。
传址调⽤,可以让函数和主调函数之间建⽴真正的联系,在函数内部可以修改主调函数中的变量;所 以未来函数中只是需要主调函数中的变量值来实现计算,就可以采⽤传值调⽤。如果函数内部要修改 主调函数中的变量的值,就需要传址调⽤。
三 、数组与指针
1首先来看这么一组代码
当打印出来时会发现,结果一样,用数组名和数组首元素打印出来的结果一模一样,那么,数组名就是数组首元素的地址。
那么,是不是在所有情况下成立呢?有两个例外:sizeof(数组名) 和 &(数组名)。
sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩, 单位是字节。
&数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素 的地址是有区别的。
我们再看一组代码:
#include <stdio.h>
void test(int arr[])
{
int sz2 = sizeof(arr)/sizeof(arr[0]);
printf("sz2 = %d\n", sz2);
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int sz1 = sizeof(arr)/sizeof(arr[0]);
printf("sz1 = %d\n", sz1);
test(arr);
return 0;
}
函数内部没有获得数组的正确的元素个数,也就是说数组传参本质上传递的时数组首元素的地址。
2 二级指针:
pa里存放的是a的地址,那么paa里面存放的其实就是pa的地址。 **paa就是先通过*pa找到pa,对pa进行解引用操作,其实就是a。
3 指针数组:其实就是存放指针的数组。
类比整型数组和字符数组,其实不难理解指针数组。
4 指针数组模拟二维数组
#include <stdio.h>
int main()
{
int arr1[] = {1,2,3,4,5};
int arr2[] = {2,3,4,5,6};
int arr3[] = {3,4,5,6,7};
//数组名是数组⾸元素的地址,类型是int*的,就可以存放在parr数组中
int* parr[3] = {arr1, arr2, arr3};
int i = 0;
int j = 0;
for(i=0; i<3; i++)
{
for(j=0; j<5; j++)
{
printf("%d ", parr[i][j]);
}
printf("\n");
}
这里的arr1、arr2、arr3本身就是数组,我们将其以二维数组的形式存入,简单联想一下二维数组的本质,就可以理解。
5 数组指针变量
举一个例子: int(*p)【10】;
p先和* 结合,说明p是一个指针变量,然后指向一个大小为10个整形的数组。所以p是一个指针,指向一个数组,叫数组指针。
我们再返回到之前的二维数组传参,我们就可以用另一种方法来写一个二维数组:
#include <stdio.h>
void test(int a[3][5], int r, int c)
{
int i = 0;
int j = 0;
for(i=0; i<r; i++)
{
for(j=0; j<c; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {{1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7}};
test(arr, 3, 5);
return 0;
}