一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情。
数组元素的指针
一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,也可以指向数组元素(把某一元素的地址放到一个指针变量中)。所谓数组元素的指针就是数组元素的地址。
可以用一个指针变量指向一个数组元素。例如:
int a[10] = {1,3,5,7,9,11,13,15,17,19}; // 定义a为包含10个整型数据的数组
int *p; // 定义p为指向整型变量的指针变量
p = &a[0]; // 把a[0]元素的地址赋给指针变量p
引用数组元素可以用下标法,也可以用指针法,即通过指向数组元素的指针找到所需的元素。使用指针法能使目标程序质量高(占内存少,运行速度快)
数组名代表数组中首元素(即序号为0的元素)的地址。
p = &a[0]; // p的值是a[0]的地址
p = a; // p的值是数组a首元素(即a[0])的地址
在引用数组元素时指针的运算
在指针已指向一个数组元素时,可以对指针进行以下运算:※
- 加一个整数 p+1
- 减一个整数 p-1
- 自加运算 p++, ++p
- 自减运算 p--, --p 两个指针相减,如p1-p2(只有p1和p2都指向同一数组中的元素时才有意义)
如果指针变量p1和p2都指向同一数组中的元素,如执行p2-p1,结果是p2-p1的值(两个地址之差)除以数组元素的长度。直接用p2-p1就可知道它们所指元素的相对距离。
两个地址不能相加,如p1+p2是无实际意义的。
通过指针引用数组元素
- 下标法 a[i]
- 指针法 *(a+i)或*(p+i)
示例:有一个整型数组a,有10个元素,要求输出数组中的全部元素。
/**
* 4.有一个整型数组a,有10个元素,要求输出数组中的全部元素。
* - 下标法
* - 通过数组名计算数组元素地址,找出元素的值
* - 用指针变量指向数组元素
* */
// 下标法
int a[10];
int i;
printf("please enter 10 integer numbers:\n");
for (i = 0; i < 10; i++)
scanf("%d", &a[i]);
for(i = 0; i < 10; i++)
printf("%d,", a[i]); // 数组元素用数组名和下标表示
printf("\n");
// 通过数组名计算数组元素地址,找出元素的值
int a[10];
int i;
printf("please enter 10 integer numbers:\n");
for (i = 0; i < 10; i++)
scanf("%d", &a[i]);
for(i = 0; i < 10; i++)
printf("%d,", *(a+i)); // 通过数组名和元素序号计算元素地址,再找到该元素
printf("\n");
// 用指针变量指向数组元素
int a[10];
int *p, i;
printf("please enter 10 integer numbers:\n");
for (i = 0; i < 10; i++)
scanf("%d", &a[i]);
for(p = a; p < a + 10; p++)
printf("%d,", *p); // 用指针指向当前的数组元素
printf("\n");
注意:
-
可以通过改变指针变量的值指向不同的元素
如果不用p变化的方法而用数组名a变化的方法行不行呢?
for(p = a; p < a + 10; a++) printf("%d,", *p);
是不行的。因为数组名a代表数组首元素的地址,它是一个指针型常量,它的值在程序运行期间是固定不变的。既然a是常量,所以a++是无法实现的
-
要注意指针变量的当前值
/**
* 5.通过指针变量输出整型数组a的10个元素
* 用指针变量p指向数组元素,通过改变指针变量的值,使p先后指向a[0]~a[9]各元素
* */
int a[10], *p, i;
p = a; // p指向a[0]
printf("please enter 10 integer numbers:\n");
for (i = 0; i < 10; i++)
scanf("%d", p++); // 输入10个整数给a[0]~a[9]
// 第一个循环结束之后p的指向已经改变了,指向a数组的末尾,下面循环p的起始值不是a[0], 而是a + 10
// ——> 所以第二个循环前需要在赋值一下 p = a;
p = a; // 重新使p指向a[0]
for(i = 0; i < 10; i++, p++)
printf("%d,", *p); // 想输出a[0]~a[9]
printf("\n");
利用指针引用数组元素,比较方便灵活,有不少技巧。可能会遇到容易使人混淆的情况,分析下面几种情况(设p开始时指向数组a的首元素 即 p = a)
- ①分析:
p++;
*p;
// p++使p指向下一元素a[1]。若在指向*p,则得到下一个元素a[1]的值
- ② *p++; 由于++和*同优先级,结合方向自右向左,因此它等价于 *(p++)。先引用p的值,实现*p的运算,然后在使p自增1,如
for (i = 0; i < 10; i++, p++)
scanf("%d", *p);
// 等价于
for (i = 0; i < 10; i++)
scanf("%d", *p++);
// 两者都是先输出*p的值,然后使p值加1.下一次循环时,*p就是下一个元素的值
-
③ *(p++)与*(++p)作用是否相同?
不相同。前者是先取*p的值,然后使p加1。后者是先使p加1,再取*p。若p初值为a(即&a[0]), 若输出*(p++),得到a[0]的值,而输出*(++p), 得到a[1]的值。
-
④ ++(*p)。表示p所指向的元素值加1,如果p=a,则++(*p)相当于++a[0],若a[0]=3, 则执行++(*p)之后a[0]的值为4。注意:是元素a[0]的值加1,而不是指针p的值加1。
- 指针是什么
- 指针变量
- 通过指针引用数组
- 通过指针引用字符串
- 指向函数的指针
- 返回指针值的函数
- 指针数组和多重指针
- 动态内存分配与指向它的指针变量
- 有关指针的小结