C语言中的指针-数组元素的指针-学习笔记-26

通过指针引用数组元素

前面我们说变量有指针,那么数组元素有没有指针呢?数组元素也有指针,并且我们也可以通过指针来引用数组元素。

数组元素的指针

我们说一个变量是有地址的,数组包含了很多的元素,每个元素都在内存中占用存储单元,这些数组元素也都有相对应的地址,指针可以指向变量也可以指向数组。所谓数组元素的指针,就是数组元素的地址。

使用数组指针

1
2
3
int a[5]={1,2,3,4,5};  //定义了包含5个元素的数组
int * p; // 定义了一个指针变量 p
p=&a[0]; //将数组的第一个元素地址传递给指针变量

我们看到,其实和变量指针类似,只不过我们这里给指针变量的地址是数组元素的地址。平时,我们引用数组元素采用的都是下标法即通过数组名+元素下标的方式表示数组。现在,我们也可以使用指针法,即通过指向数组元素的指针来找到所需要的元素。

使用指针法调用数组元素,可以提升目标程序质量,占用内存少,运行速度快。

在 C 语言中,数组名代表的(不包括形参的,因为那就是个摆设)都是该数组中首元素的地址。所以:

1
2
3
4
int a[5]={1,2,3,4,5};
int * p;
p=&a[0];
p=a;

最后给 p 赋值的两个语句,其实是等价的,因为数组名 a 表示的就是数组 a 的 0 号元素的地址。

注意
数组名不代表整个数组,只代表该数组的 0 号元素的起始地址。

引用数组元素指针的运算

我们知道,指针就是地址,对地址进行算术运算有什么意义呢?其实乘除运算是没有意义的,但是加减运算就非常有意义了。
从上面我们知道,数组名称表示的是该数组首元素的地址,那么我们如果需要让指针只想第二个元素呢?

1
2
3
4
5
int a[5]={1,2,3,4,5};
int * p;
p=a;
p=p+1;
p=&a[1];

上面的 p=p+1 和 p=&a[1] 其实是等价的,都是把数组的第二个元素地址赋值给 p,但是区别是,我们使用指针的加减法更加简约和易懂。

指向数组元素的指针运算法则

1
2
3
4
5
6
7
8
9
int a[5]={1,2,3,4,5};
int * p,*q;
p=a;
q=a;
p=p+1; //地址直接加一个整数
p=p-1; //地址直接减一个整数
p++; ++p; //地址的自加运算
p--; --p; //地址的自减运算
p=p-q; //指向同一数组的两个指针相减

指针地址的加减运算

如果指针变量 p 已经指向数组中的一个元素,则:
p+1 指向同一数组中的下一个元素;
p-1 指向同意数组中的上一个元素;

这里的 p 的加减1,并不是指 p 的值(地址)加减 1 ,而是加上一个数组元素所占用的字节数。

实际上,p+1 代表的是 (p+1) x d ,d 是一个数组元素所占用的字节数,对 int 、float 、long 类型时,d=4, 对于 char 类型是,d=1, 具体系统怎么知道 d 代表的字节数,是因为在定义指针变量的时候,声明了基类型,根据基类型,编译器会自动给 d 赋值。

指针跳转到指定元素

我们可以直接给指针赋值某一元素的地址,但是我们如果想从首元素直接跳到3号元素该怎么办呢?

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main(){
int *p;
int a[5]={1,2,3,4,5};
p=a;
p=p+3;
printf("指针调用:%d\n",*p);
printf("下标调用:%d\n",a[3]);
}

没错,我们可以在首元素的基础上,直接加上想要跳转到的元素下标,比如上面,我们想把指针跳转到 3 号元素,那么我们就在首元素的基础上+3即可。当然,我们也可以在3的基础上 -1 将指针指向 2 号元素。

用指针输出数组元素

我们知道了如何调用指针和如何跳转到我们需要的指针位置,现在,和普通指针变量相同,我们在指针变量前加 * 号,就可以表示当前指向数组元素的指针所指向的值了。

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main(){
int *p;
int a[5]={1,2,3,4,5};
p=a;
printf("指针2号元素:%d\n",*(p+1));
printf("指针3号元素:%d\n",*(a+2));
printf("数组4号元素:%d\n",a[3]);
}

我们看到,可以表示数组元素的方式有三种:

  1. 指针调用,通过指针变量前加*,表示数组元素。
  2. 因为 a 表示的是首元素地址,所以 a 也可以进行指针的运算
  3. 直接使用下标法引用数组元素。

两个指针地址相减

既然不同元素之间的指针地址,都只差4个字节的倍数,那么我们如果将指向 a[3] 的地址减去指向 a[1] 的地址会得到什么结果呢?

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main(){
int a[5]={1,2,3,4,5};
int *p,*p1,*p2;
p1=&a[3];
p2=&a[1];
p=p1-p2;
printf("得到的是:%d\n",p);
}

结果是:『得到的是:2』

上面我们用3号元素的地址减去了1号元素的地址,得到的就是两个地址之间的差除以类型的字节数。如果:
a[3] 的地址为:2022;
a[1] 的地址为:2014;
最后的得到的是:(2022-2014)/4
上面的4是字节数,是数组的数据类型决定的。

所以上面的例子中,我们得到的结果是2,也就是3号元素和1号元素之间差2个元素,这样我们就能知道两个元素的相对位置了。

尾巴

这是我的个人学习笔记,主要是应付考研复习使用,充斥着一些吐槽和个人观点,并不严谨,欢迎大家参考、指正。


-------------The End-------------
欢迎请我喝咖啡哦~!