指针数组
秘诀:括号优先,先右后左,由近及远
指针数组是一个数组,其中每个元素都是一个指针。指针数组可以用于存储指向不同数据类型的指针,例如字符、整数或结构体等。
int *p[n]; //定义了一个指针数组,数组大小为n,数组中的每个元素都是一个int*指针
存储指向整型数组的指针
#include <stdio.h>
int main() {
// 声明几个整型数组
int arr1[] = {1, 2, 3};
int arr2[] = {4, 5, 6};
int arr3[] = {7, 8, 9};
// 声明一个指针数组,每个元素是一个指向整型的指针
int *arr[] = {arr1, arr2, arr3};
// 打印指针数组中的每个数组的内容
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printf("arr[%d][%d] = %d\n", i, j, arr[i][j]);
}
}
return 0;
}
运行结果:
arr[0][0] = 1
arr[0][1] = 2
arr[0][2] = 3
arr[1][0] = 4
arr[1][1] = 5
arr[1][2] = 6
arr[2][0] = 7
arr[2][1] = 8
arr[2][2] = 9
存储指向字符串的指针
#include <stdio.h>
int main() {
// 声明一个指针数组,数组中的每个元素都是一个指向字符常量的指针
const char *arr[] = {"Hello", "World", "Pointer", "Array"};
// 打印指针数组中的每个字符串
for (int i = 0; i < 4; i++) {
printf("arr[%d]: %s\n", i, arr[i]);
}
return 0;
}
运行结果:
arr[0]: Hello
arr[1]: World
arr[2]: Pointer
arr[3]: Array
问题思考
有同学会问数组里存放的不是字符串吗,指针数组里存放的不应该是指针吗?一开始我也有这样的疑问,后来通过查阅相关资料后终于理解。
解答:
"Hello", "World", "Pointer", 和 "Array" 确实是 arr
数组中的元素,但它们在数组中存储的是指向这些字符串的指针,而不是字符串本身。字符串本质就是地址,地址是指针类型的数据;数组名也是一样。对于本例指针数组,每个元素都是一个 const char*
类型的指针,指向相应的字符串常量。 (友友们是否理解了)
数组指针
数组指针是一种特殊的指针,用来存放数组的地址。在C语言中,数组指针的定义形式为 int (*p)[n]; ,其中 p 是指向一个包含 n 个 int 类型元素的数组的指针。
数组指针与指向数组首元素的指针不同,它直接指向 整个数组 。
#include<stdio.h>
int main(){
int arr[20] = {1,2,3,4,5,6,7,8};
int (*p)[20] = &arr;
//数组的大小
printf("arr = %28lu\n",sizeof(arr));
printf("*p = %29lu\n",sizeof(*p));
//打印首元素地址
printf("arr = %28p\n",arr);
//打印数组整体地址
printf("&arr = %27p\n",&arr);
//表示加一个数组整体地址大小
printf("&arr + 1 = %23p\n",&arr+1);
printf("(void*)(p + 1) = %17p\n",(void*)(p + 1));
//表示加一个数组元素大小
printf("arr[0] + 1 = %21p\n",&arr[0] + 1);
printf("arr + 1 = %24p\n",arr+1);
printf("(void*)((*p) + 1) = %13p\n",(void*)((*p) + 1));
return 0;
}
运行结果:
arr = 80
*p = 80
arr = 0x7fff2475a290
&arr = 0x7fff2475a290
&arr + 1 = 0x7fff2475a2e0
(void*)(p + 1) = 0x7fff2475a2e0
arr[0] + 1 = 0x7fff2475a294
arr + 1 = 0x7fff2475a294
(void*)((*p) + 1) = 0x7fff2475a294
例如,如果我们有一个 int
类型的数组 arr[5]
,我们可以定义一个数组指针来指向它:
int arr[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &arr;
这里,p
是一个数组指针,它指向由5个 int
元素组成的数组 arr
。通过数组指针,我们可以访问数组中的元素,例如 (*p)[i]
将访问 arr
数组中的第 i
个元素。
理解 arr
和 &arr
的区别
-
arr
:arr
是一个数组名,在表达式中它会衰减为指向数组首元素的指针。- 例如,对于
int arr[20]
,arr
的类型是int*
,指向第一个元素arr[0]
。
-
&arr
:&arr
是整个数组的地址,它的类型是int (*)[20]
,即指向包含20个整数的数组的指针。&arr
指向整个数组,而不是数组的第一个元素。
为什么 int (*p)[20] = &arr;
是正确的
p
的类型是int (*)[20]
,表示p
是一个指向包含20个整数的数组的指针。&arr
的类型也是int (*)[20]
,表示它是一个指向包含20个整数的数组的指针。- 因此,
int (*p)[20] = &arr;
类型匹配,是正确的。
为什么 int (*p)[20] = arr;
是不正确的
arr
的类型在表达式中衰减为int*
,表示它是一个指向int
的指针。p
的类型是int (*)[20]
,表示它是一个指向包含20个整数的数组的指针。int*
和int (*)[20]
类型不匹配,因此编译器会报错。
理解数组指针和解引用
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &arr;
// 访问数组元素
for (int i = 0; i < 5; i++) {
printf("(*p)[%d] = %d\n", i, (*p)[i]);
}
// 也可以直接使用 p[0] 访问数组元素,因为 p[0] 等价于 (*p)
for (int i = 0; i < 5; i++) {
printf("p[0][%d] = %d\n", i, p[0][i]);
}
return 0;
}
运行结果:
(*p)[0] = 1
(*p)[1] = 2
(*p)[2] = 3
(*p)[3] = 4
(*p)[4] = 5
p[0][0] = 1
p[0][1] = 2
p[0][2] = 3
p[0][3] = 4
p[0][4] = 5
1.声明数组和数组指针:
int arr[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &arr;
arr
是一个包含5个int
元素的数组。p
是一个指向arr
的指针,它的类型是int (*)[5]
。
2.解引用数组指针:
*p
解引用数组指针p
,得到它所指向的数组arr
。(*p)
的类型是int[5]
,即包含5个int
元素的数组。
3.访问数组元素:
(*p)[i]
访问数组arr
中的第i
个元素。p[0][i]
也可以访问数组元素,因为p[0]
等价于(*p)
。
关键点
p
是指向数组的指针,直接使用p
得到的是指向数组的指针,而不是数组本身。- 通过解引用
p
(即*p
),我们得到数组arr
,然后可以使用数组下标来访问数组中的元素。 p[0]
等价于(*p)
,因为p
指向的是数组的首地址,p[0]
解引用第一个元素,即整个数组。
问题思考
数组指针为什么被称为行指针 ?(参考上一代码运行结果p[0][0], p[0][1]......)
标签:arr,20,数组,指向,int,详细,指针 From: https://blog.csdn.net/qq_62850449/article/details/140161748