【C语言进阶】指针数组与数组指针

【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个整型元素的数组。


总结:

  本节介绍了数组指针与指针数组的使用;给出了数组指针的使用场景(一般用在二维数组传参)。


感谢您的阅读!如有任何错误,欢迎您的批评指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值