C语言之指针(四)

一、前言

        哈喽大家好,经过前三次的学习,我们已经了解到了指针的诸多概念,同时也分别从计算机内存、&符号、机器位数和野指针等多方面去研究指针,那么接下来,我们要研究的是关于指针在数组中的应用,在此也附上上一篇关于指针的文章,以便大家参考。C语言之指针(三)-CSDN博客

二、数组名的理解

        我们在学习数组时,相信大家也学习过如下代码:

#include<stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* a = arr;
	return 0;
}

        上述代码是将arr数组中的首地址放入了一个整形指针变量a中,在此,arr则代表的是数组的首元素地址,由代码可知:

#include<stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* a = arr;
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
	printf("%p\n", a);
	return 0;
}

运行结果如下:

        我们发现数组名和首元素地址以及指针变量a所打印出的地址都是一样的,数组名就是首元素的地址(数组中第一个元素)。但是,需要注意的是,对于数组名就是首元素地址是正确的,不过却有两个例外:

        (1)sizeof(数组名):sizeof中单独存放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。

        (2)&(数组名):&(数组名)表示的是整个数组的地址,为了方便理解,我们用代码体现:

#include<stdio.h>

int main()
{
	int arr[3] = { 1,2,3 };
	int(*a)[3] = &arr;
	printf("%p\n", arr);//首元素地址
	printf("%p\n", &arr);//整个数组的地址
	printf("%p\n", &arr + 1);//数组地址+1的地址
	printf("%p\n", a + 1);//数组地址+1的地址
	return 0;
}

代码结果如下:

        对于整个数组地址来说,它的起始地址为首元素地址,但是&arr与arr不同之处在于,arr+1跳过的是1个元素,4个字节,而对于&arr+1来说,他跳过的是数组中全部的元素个数,也就是元素个数*4字节。

        如上图所示,arr首元素地址为0073FD90,当他跳过3*4字节后,就变成了0073FD9C,正好跳过12个字节。

        所以我们以后写代码时,要格外注意这些细节。

总结:数组名是数组首元素的地址,但是有2个例外。

三、使用指针访问数组

        通常情况下,我们写代码打印数组中的每一个元素,如下所示:

#include<stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

        但是如果通过指针来打印每一个元素,如下所示:

#include<stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* a = arr;
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *(a + i));
	}
	return 0;
}

四、一维数组传参的本质

        接下来,我们讲一下数组传参的问题。

        首先,对于计算数组内部元素个数的问题,我们通常会以如下代码实现:

#include<stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int len = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", len);
	return 0;
}

        但是如果我们把计算数组元素个数的代码写成一个函数,那么这种方法还能够实现吗?

#include<stdio.h>

void my_size(int arr[])
{
	int len = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", len);
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int len = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", len);
	my_size(arr);

	return 0;
}


        由上图可知,通过传参的方式求数组长度是行不通的。

       这就要学习数组传参的本质了,上个模块我们学习了:数组名是数组首元素的地址;那么在数组传参的时候,传递的是数组名,也就是说本质上数组传参传递的是数组首元素的地址。

五、二级指针

        指针是地址,那么存储指针的被称为指针变量,但指针变量也是变量,是变量就会有地址,而 存储指针变量地址的就叫做二级指针。为了大家更好的去理解二级指针的关系概念,我们还是以数形结合的方式去理解,具体如下:

对二级指针的运算:

        通过解引用pnn(*pnn)得到的是pn,也就是n的地址,再进行一步解引用(**pnn)就能直接访问n。

        由此可见,对不同的指针通过不同的解引用都可以访问n,以达到对n的操作。

六、指针数组

        对于指针数组的学习,我们可以类比一下整数数组和字符数组,其中整数数组是存放整数的数组,字符数组是存放字符的数组,而指针数组就是存放指针的数组。

        指针数组中每个元素都是指针,而这些指针又可以指向一块区域。

         总而言之,指针数组的本质还是数组。

  • 23
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值