指针与数组的结合
示例 1:指针访问数组元素
通过==指针访问数组元素=的例子:
#include <stdio.h>int main() {int arr[5] = {1,2,3,4,5};//int *p1 = &arr;int *p1 = (int *)&arr; // 需要强制类型转换int *p2 = arr;printf("*p1:%d\n", *(p1 + 1)); // 应该是访问第二个元素printf("*p2:%d\n", *(p2 + 1)); // 应该是访问第二个元素return 0;
}
p1
被初始化为数组的地址,但是由于没有进行强制类型转换,这里会有一个编译警告。通过(int *)&arr
进行强制类型转换可以解决这个问题。p2
被初始化为数组的第一个元素的地址。
示例 2:指针访问数组中的不同元素
通过指针访问数组中的不同元素:
#include <stdio.h>int main() {int arr[5] = {1,2,3,4,5};int *p2 = &arr[2];printf("*p2-1:%d\n", *(p2 - 1)); // 访问第二个元素printf("*p2:%d\n", *p2); // 访问第三个元素printf("*p2+1:%d\n", *(p2 + 1)); // 访问第四个元素return 0;
}
p2
被初始化为指向数组的第三个元素。通过指针加减运算可以访问数组中的上一个和下一个元素。
示例 3:数组指针
数组指针: 专门用来指向一个数组的指针的例子:
#include <stdio.h>int main() {int arr[5] = {1,2,3,4,5};int (*p)[5] = &arr;//定义一个 名为p 的指针,并且确定他指向的类型为int [5] ,一个拥有5个元素的整型数组//注意 []的优先级大于*,所以会有括号将*p括起来printf("arr:%p\n", &arr);printf("%p---%d\n", p, (*p)[2]); // 访问第三个元素printf("%p---%d\n", p + 1, (*(p + 1))[2]); // 已经越界访问return 0;
}
p
是一个指向整型数组的指针,这个数组有 5 个元素。p+1
实际上会跳过整个数组,导致越界访问。–>实际上是加一个p的类型,由于p是一个整型数组[5],所以会越界。
示例 4:指针数组
指针数组:专门用来存放指针的数组,称为指针数组
#include <stdio.h>int main() {int a = 100;int b = 250;int c = 550;int d = 256;int e = 998;int *p[5] = {&a, &b, &c, &d, &e}; // 定义一个名字为 p 的数组,数组中存放的是 int 型指针for (size_t i = 0; i < 5; i++) {printf("*p[%ld]:%d \n", i, *(p[i])); // 访问指针数组中的每个指针指向的值}return 0;
}
p
是一个指针数组,每个元素都是一个指向整型数据的指针。- 通过
*(p[i])
可以访问每个指针指向的值。
注意事项:
- 指针的类型决定了指针运算时的步长,
int *
类型的指针步长为 4 字节(在 32 位系统中),double *
类型的指针步长为 8 字节。 - 数组指针和指针数组是两个不同的概念。数组指针指向一个数组,指针数组是一个数组,数组的元素是指针。
- 指针运算时要确保不越界访问,否则会导致不可预测的行为甚至崩溃。