【C语言进阶】指针数组与数组指针
二、指针数组
指针数组是一个存放指针变量的数组。
在C语言初阶学习中的《指针》章节已经介绍过指针数组,故在此只给出一个简单的示例。
代码示例:
#include<stdio.h>
int main()
{
//指针数组
int a = 10;
int b = 20;
int c = 30;
int* pa = &a;
int* pb = &b;
int* pc = &c;
int* parri[] = { pa,pb,pc };//指针数组,数组存放整型指针变量
return 0;
}
解释说明:
1 指针数组,数组元素是指针变量。
三、数组指针
1 数组指针的定义
数组指针是一个指向数组类型的指针变量。存放的是整个数组(数组类型)的地址。
示例:
int *p1[10];//指针数组
int (*p2)[10];//数组指针
说明:
1 上述示例中,p1
是一个指针数组,存放整型指针;存放的元素类型是 int*
,数组类型是 int* [10]
。
2 上述示例中,p2
是一个数组指针,指针指向整个数组;指向的类型是 int [10]
。
3 数组指针:指向数组的指针变量。
int (*p)[10];
//解释:
//p先与*结合表示p是一个指针变量
//p指向的是一个大小为10个整型的数组类型。
//p指向对象的类型是:int [10]
//
//此外,还要注意到:[]的优先级是要高于*的,所以要加上(),让p与*先结合。
注意:
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//int [10] *p = &arr;//error;意思正确,语法形式错误
int (*p)[10] = &arr;//数组指针变量,指针指向一个有10个int型元素的数组。
2 &数组名与数组名
数组名表示数组首元素的地址。
&数组名表示一个数组类型的地址。
代码示例:
#include<stdio.h>
int main()
{
//数组名与&数组名
int arr[10] = { 0 };
printf("%p\n", arr);
printf("%p\n", arr + 1);
printf("%p\n", &arr[0]);
printf("%p\n", &arr[0] + 1);
printf("%p\n", &arr);
printf("%p\n", &arr + 1);
return 0;
}
解释说明:
1 指针变量的类型决定指针±1跳过几个字节。
2 地址比较:
%p arr 0136FC60
%p arr+1 0136FC64
//相差0x4 --> 4个字节 --> 一个int类型的大小
%p &arr[0] 0136FC60
%p &arr[0]+1 0136FC64
//相差0x4 --> 4个字节 --> 一个int类型的大小
%p &arr 0136FC60
%p &arr+1 0136FC88
//相差0x28 --> 40个字节 --> 一个int[10]类型的大小 --> 一个数组类型的大小
3 对数组名取地址,表示取出一个数组类型对象的地址,该地址的类型是:int (*) [10]
。
4 对一个数组类型的地址±1,表示跳过一个数组类型大小的字节,即跳过一整个数组的大小。
3 数组指针的使用
数组指针变量中存放的是数组类型的地址。
- 一般用在二维数组传参,控制访问元素是一维数组的数组(二维数组)。
3.1 示例1
代码示例:
#include<stdio.h>
int main()
{
//数组指针
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr; //把数组类型对象的地址赋值给数组指针变量
//p -> &arr -- int(*)[10]
printf(" p <==> %p\n", p); //指针p的值是一个数组类型的地址
printf("&arr <==> %p\n", &arr);//数组类型的地址
//*p -> *(&arr) -> arr -- int*
printf(" *p <==> %p\n", *p); //*p表示取出p变量的内容,是数组名arr
printf(" arr <==> %p\n", arr); //数组名表示数组首元素的地址
//(*p)+i -> arr+i -> &arr[i] -- int*
printf(" (*p)+1 <==> %p\n", (*p) + 1);//*p表示数组名arr,+1表示跳过一个元素的地址(第二个元素的地址)
printf(" arr+1 <==> %p\n", arr + 1); //数组名+1表示跳过一个元素的地址(第二个元素的地址)
printf("&arr[1] <==> %p\n", &arr[1]); //第二个元素的地址
//*((*p)+i) -> *(arr+i) -> arr[i] -- int
printf("*((*p)+1) <==> %d\n", *((*p) + 1));//下标为1的元素的值
printf(" *(arr+1) <==> %d\n", *(arr + 1)); //下标为1的元素的值
printf(" arr[1] <==> %d\n", arr[1]); //下标为1的元素的值
//(*p)[i] -> arr[i] -- int
printf("(*p)[2] <==> %d\n", (*p)[2]);//*p表示数组名arr,(*p)[2]表示下标为2的元素的值
printf(" arr[2] <==> %d\n", arr[2]); //下标为2的元素的值
return 0;
}
解释说明:
1 每一行的值都相同:
//p -> &arr -- int(*)[10]
//*p -> *(&arr) -> arr -- int*
//(*p)+i -> arr+i -> &arr[i] -- int*
//*((*p)+i) -> *(arr+i) -> arr[i] -- int
//(*p)[i] -> arr[i] -- int
注意:
int arr[10] = {0};
//int *p = &arr;//error;类型不匹配
// p -> int*类型
//&arr -> int(*)[10]类型
3.2 示例2
代码示例:
#include<stdio.h>
//二维数组传参
//void print_arr1(int arr[3][5], int row, int col)//二维数组传参可以省略行,但不能省略列
void print_arr1(int arr[][5], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
//数组指针传参
//二维数组元素类型: int[5]
//二维数组元素地址类型:int(*)[5]
void print_arr2(int(*arr)[5], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
//数组指针的使用
int arr[3][5] = { {1,2,3,4,5}, {3,4,5,6,7}, {5,6,7,8,9} };
//二维数组传参
printf("二维数组传参:>\n");
print_arr1(arr, 3, 5);
//二维数组相当于是一维数组的一维数组
//二维数组第一行相当于是二维数组的第一个元素
//数组名arr表示首元素的地址
//arr相当于是第一行的地址,是一维数组的地址
//数组指针传参
printf("数组指针传参:>\n");
print_arr2(arr, 3, 5);
return 0;
}
解释说明:
1 二维数组的数组元素可以看作是一个一维数组;二维数组相当于是存放一维数组的数组。
2 二维数组数组名:
arr -> 二维数组首元素的地址 -> 第一行的地址 -> 一维数组的地址 -> arr[0](相当于“一维数组名”)
//类型:int(*)[5]
3 数组传参不会额外拷贝一份数组,而是创建指针存放传过来的地址。
4 print_arr2()
:该函数中使用 arr[i][j]
表示二维数组元素。
5 数组指针接收二维数组的地址:( int(*)[5]
)
p+i --> 第i个元素的地址 --> 一维数组的地址(类型:int(*)[5])
*(p+i) --> 第i个元素 --> 第i行首元素的地址(类型:int*)
*(p+i)+j --> 第i行第j列元素的地址 --> 第i个元素(一维数组)中第j个元素的地址(类型:int*)
*(*(p+i)+j) --> 第i行第j列元素 --> 第i个元素(一维数组)中第j个元素(类型:int)
3.3 小练习
描述下面代码的意思:
int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];//int(*)[5]
说明:
1.整型数组,数组存放5个 int
型元素。
2.整型指针数组,数组存放10个 int*
型元素。
3.整型数组指针,指针指向的对象为数组类型,类型为 int(*)[10]
。
4.存放整型数组指针的数组,数组存放10 个整型数组指针,元素类型(指针类型)为 int(*)[5]
;指针指向存放5个整型元素的数组。
总结:
本节介绍了数组指针与指针数组的使用;给出了数组指针的使用场景(一般用在二维数组传参)。
感谢您的阅读!如有任何错误,欢迎您的批评指正!