指针(二):数组指针

数组名的理解

在介绍数组指针之前先通过一段代码了解一下数组名的本质是什么。

#include<stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5 };
	int* p1 = &arr[0];
	int* p = arr;
	printf("%p\n", p1);
	printf("%p", p);
	return 0;
}

第一行代码我们取出数组第一个元素的地址放在p1里面,第二行将数组名直接赋值给p,如图,以地址的形式打印出来的地址一模一样,说明数组名本质上就是数组首元素的地址。
同时也说明我们调用函数时以数组为参数传参时传的也就是数组首元素地址。
在这里插入图片描述
但是在一些特殊情况下的数组名不代表首元素的地址。
如:
sizeof(数组名):sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩,单位是字节。
&数组名:这里取地址取的是整个数组的地址。
除了这两种情况,其他的地方使用数组名都是数组首元素地址。
这个时候就会有人好奇去尝试打印整个数组的地址,如下列带代码:

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

发现三个打印的地址一模一样,那数组整个地址与数组首元素地址区别是什么?

数组整个地址与数组首元素地址区别

#include <stdio.h>
int main()
{
 int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
 printf("&arr[0] = %p\n", &arr[0]);
 printf("&arr[0]+1 = %p\n", &arr[0]+1);
 printf("arr = %p\n", arr);
 printf("arr+1 = %p\n", arr+1);
 printf("&arr = %p\n", &arr);
 printf("&arr+1 = %p\n", &arr+1);
 return 0;
}

在这里插入图片描述
上述代码中printf两行为一组,每一组代码都是取出来一个地址给地址加1。
可以看出来前两组代码的值变化都是4个字节(原因在上一篇指针(一)里面介绍过),而最后一组变化范围很大。
原因就是最后一组取出来的是整个数组的地址,让地址加1就是加整个数组的大小的地址,这段代码中arr的大小是40个字节,所以让整个数组的地址加1也就是加40个字节,但是取数组地址并用printf打印也是打印数组首元素的地址。

指针的形式访问数组

用指针的形式来输入和输出数组:

int main()
{
	int arr[5] = { 0 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i < sz; i++)
	{
		scanf("%d", arr + i);//arr数组首元素地址,循环一次加1
	}
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(arr+i));//每循环一次地址加1并解引用
	}
	return 0;
}

运行结果如图:
在这里插入图片描述
这只是指针的一种描写形式,还有很多形式与它等价,代码与结构如下图所示:
在这里插入图片描述

冒泡排序

冒泡排序本质上就是相邻两个地址之间进行比较然后进行排序。

void bubble_sort(int arr[], int sz)//参数接收数组元素个数{
 int i = 0;
 for(i=0; i<sz-1; i++)
 {
 int flag = 1;//假设这⼀趟已经有序了
 int j = 0;
 for(j=0; j<sz-i-1; j++)
 {
 if(arr[j] > arr[j+1])
 {
 flag = 0;//发⽣交换就说明,⽆序
 int tmp = arr[j];
 arr[j] = arr[j+1];
 arr[j+1] = tmp;
 }
 }
 if(flag == 1)//这⼀趟没交换就说明已经有序,后续⽆序排序了 break;
 }
}
int main()
{
 int arr[] = {3,1,7,5,8,9,0,2,4,6};
 int sz = sizeof(arr)/sizeof(arr[0]);
 bubble_sort(arr, sz);
 int i = 0;
 for(i=0; i<sz; i++)
 {
 printf("%d ", arr[i]);
 }
 return 0;
}

二级指针

在我们取变量地址时会创建一个指针变量来存放这个地址,有变量就会有地址,二级指针就是用来存放指针变量地址的变量。

int main()
{
	int a = 0;
	int* p = &a;//一级指针
	int** p = &p;//二级指针
	return 0;
}

那么二级指针怎么找到变量a呢?
对它进行两次解引用就好了:第一次解引用找到p,找到p后再对p进行解引用就找到了a。

指针数组

整形数组是代表数组的每个元素都是整形,那指针数组也就是说每个数组元素都是一个指针变量。

int* arr[5]={a,b,c,d,e};//这里a,b,c,d,e都是一个整形类型的指针变量

指针数组模拟二维数组

int main()
{
	int arr1[3] = { 1,2,3 };
	int arr2[3] = { 4,5,6 };
	int arr3[3] = { 7,8,9 };
	int* arr4[3] = { arr1,arr2,arr3 };
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d", arr4[i][j]);
		}
		printf("\n");
	}
	return 0;
}

在这里插入图片描述
-----------------------分隔符
关于数组指针的内容就介绍完了,感谢观看。
有错请指正,谢谢。

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值