C语言:深入理解指针(3)

目录

一、数组名的理解

二、用指针访问数组

三、一维数组传参的本质

四、冒泡排序

五、二级指针

六、指针数组

七、指针数组模拟二维数组

八、结语


一、数组名的理解

数组名其实就是首元素的地址

cs 复制代码
int arr[3] = {1,2,3};
printf("arr   :%p\n" ,arr);
printf("arr[0]:%p\n" ,&arr[0]);

可以看到,数组名确实就是首元素的地址,但是有没有想到这个语句?

cs 复制代码
int r = sizeof(arr)/sizeof(arr[0]);

这是用来求数组的元素个数的,在这里,数组名是个例外,它表示整个数组

既然数组名就是首元素地址,那么 &arr 又代表这什么呢?

cs 复制代码
int arr[3] = {1,2,3};
printf("arr:    %p\n",arr);
printf("arr+1:  %p\n" ,arr+1);
printf("&arr:   %p\n" ,%arr);
printf("&arr+1: %p\n" ,&arr+1);

可以看到,&arr 和 arr 的地址是一样的,但是&arr 拥有的权限是整个数组,而arr的权限只有一个元素,因此,他们分别+1的结果就不同了

二、用指针访问数组

通常我们访问数组元素使用下标的

cs 复制代码
printf("%d ",arr[2]);

既然数组名就是首元素地址,那我是不是可以通过指针来访问呢,比如解引用首元素的指针?

cs 复制代码
printf("%d ",*arr);

没问题,而我们又知道数组在内存中的存储是连续的,那我知道了首元素的地址,那我岂不是也可以找到其他元素的地址,然后对其解引用,就可以访问其他数组元素了?

cs 复制代码
for(int i = 0; i<3;i++)
{
   printf("%d " ,*(arr+i));
}

没有问题,到此,我们可实现用指针访问数组了。

但是,你有没有想过,数组名 arr 是地址,可以通过 arr[2] 来访问第三个元素,而我们的指针也存放的是地址,那我们的指针可不可以也能这样 P[2] 访问其他元素呢?

cs 复制代码
int* p = arr;
for(int i = 0; i<3;i++)
{
   printf("%d ",p[i]);
}

也没问题!是不是很震惊!当然,要注意的是,是用了方括号就不要再带解引用了哦

我要开始搞事情了,由以上分析可得:***(p+i) == p[ i ] 而 *(p+i) == *(i+p) == i[ p ]**了?

cs 复制代码
int* p = arr;
for (int i = 0; i < 3; i++)
{
	printf("%d ",i[p]);
}
return 0;

成功了!是不是更感觉很震惊了!当然,这是另类的写法,我们一般还是要按照常理出牌,不然会被说成是猪队友的

三、一维数组传参的本质

大家有没有经历过在自己写的函数中,求数组长度是错误的!

cs 复制代码
void Fun_arr(int arr[])
{
   int sz = sizeof(arr)/sizeof(arr[0]);
}

为什么求出来是1呢,这是因为数组传参本质上传的就是首元素的地址,所以求出来只有一个元素

四、冒泡排序

核心思想:两两相邻元素的比较

|---|---|---|---|---|
| 1 | 4 | 2 | 5 | 3 |

这是一个无序数列,现在我们要将其变为升序序列,那就先把第一个元素和第二元素比较,把大的方后面,1 小于4,所以不用管,接下来比较第二个元素和第三个元素,4大于2 ,我们需要把大的放后面,把2和4位置对调:

|---|---|---|---|---|
| 1 | 2 | 4 | 5 | 3 |

最后就变成了:

|---|---|---|---|---|
| 1 | 2 | 4 | 3 | 5 |

发现没有,我们进行一次,就把最大的弄的最后面去了,那我们再多进行几次,不就把第二大,第三大的也弄后面去了?

第二次:

|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 |

这里刚好就完成了排序。冒泡排序需要视频讲解更方便,图文讲解起来比较费劲,我这里就就不多说了,下面是冒泡排序的代码:

cs 复制代码
void Bubble_sort(int arr[], int sz)
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j+1])
			{
				//交换
				int mid = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = mid;
			}
		}
	}
}

五、二级指针

二级指针就是该指针指向的变量仍然是一个指针,相应的还有三级指针,n级指针

cs 复制代码
int a = 10;
int* pa = &a;
int** ppa = &pa;//这里的ppa就是二级指针了

int** ppa = &pa; 这里的 int* 说明ppa指向的变量的类型,第二个 * 说明ppa是指针变量

当然你要是想找到a,就要对ppa进行两次解引用。

六、指针数组

前面将指针的时候说了,有整型数组,里面放的全是整型,字符型数组,里面放的全是字符型,那么,指针数组里面放的全部都是指针喽。

cs 复制代码
int a = 10;
int b = 20;
int c = 30;
int* pa = &a;
int* pb = &b;
int* pc = &c;
int* arr[3] = {pa,pb,pc};

七、指针数组模拟二维数组

为了巩固指针数组的理解,我们需要完成一个任务:用指针数组模拟一个二位数组

在学习二维数组的时候,讲了二维数组在内存中的存储是一行挨着一行的,那我们可以把每行的首元素的地址作为一个数组的元素,具体来讲就是这个样子:

cs 复制代码
int arr1[] = {1,2,3,4,5};
int arr2[] = {2,3,4,5,6};
int arr3[] = {3,4,5,6,7};
int* str[] = {arr1,arr2,arr3};
for(int i = 0; i<3;i++)
{
   for(int j = 0; j<5;j++)
   {
      printf("%d ", str[i][j] );
   }
   printf("\n");
}

关于这里的打印,前面说了,可以用指针加方括号的形式打印,所以就写成了 str[ i ][ j ],因为 str[ i ] 表示的是一个地址嘛。

八、结语

指针的学习没有终点。继续探索,挑战自己,你将发现C语言指针的强大之处,并能编写出更高效、更灵活的代码。愿你在C语言指针的世界里越走越远,收获满满!

相关推荐
悦悦子a啊9 分钟前
PTA:jmu-ds-最短路径
c++·算法·图论
Despacito0o22 分钟前
RGB矩阵照明系统详解及WS2812配置指南
c语言·线性代数·矩阵·计算机外设·qmk
Kidddddult27 分钟前
力扣刷题Day 46:搜索二维矩阵 II(240)
算法·leetcode·力扣
小王努力学编程1 小时前
高并发内存池(三):TLS无锁访问以及Central Cache结构设计
jvm·数据结构·c++·学习
草莓啵啵~1 小时前
数据结构--二叉树
数据结构
Watink Cpper1 小时前
[数据结构高阶]并查集初识、手撕、可以解决哪类问题?
数据结构·图论··并查集
不是吧这都有重名2 小时前
[论文阅读]Deeply-Supervised Nets
论文阅读·人工智能·算法·大语言模型
homelook2 小时前
matlab simulink双边反激式变压器锂离子电池均衡系统,双目标均衡策略,仿真模型,提高均衡速度38%
算法
什码情况3 小时前
星际篮球争霸赛/MVP争夺战 - 华为OD机试真题(A卷、Java题解)
java·数据结构·算法·华为od·面试·机试
天上路人3 小时前
采用AI神经网络降噪算法的通信语音降噪(ENC)模组性能测试和应用
人工智能·神经网络·算法