深度解析指针与数组:探索内存管理的艺术

目录

1.数组名的理解

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

&数组名,这里的数组名表示整个数组,取出的是整个数组的地址 (整个数组的地址和数组首元素的地址是有区别的)

2.使用指针访问数组

arr[i]==>*(arr+i)等价

数组与指针的联系:

3.一维数组传参的本质

4 .冒泡排序

5.二级指针

解引用

6.指针数组

指针数组是数组还是指针?

7.指针数组模拟二维数组


 1.数组名的理解


我们发现数组名和数组首元素的地址打印出的结果一模一样,数组名就是数组首元素(第一个元素)的地址。

 数组名如果是数组首元素的地址,那下面的代码怎么理解呢?

输出的结果是:40,如果arr是数组首元素的地址,那输出应该的应该是4/8才对。

其实数组名就是数组首元素(第一个元素)的地址是对的,但是有两个例外:

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

&数组名,这里的数组名表示整个数组,取出的是整个数组的地址 (整个数组的地址和数组首元素的地址是有区别的)

除此之外,任何地方使用数组名,数组名都表示首元素的地址。

 图解:

2.使用指针访问数组

为什么访问数组的时候可以使用指针呢?

1.数组在内存中是连续存放的

2.指针+-整数运算,方便我们获得每一个元素的地址

int main()
{
	int arr[10] = { 0 };
	//使用指针来访问数组
	int sz = sizeof(arr) / sizeof(arr[0]);
	//输入10个值
	int* p = arr;
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		//输入1个值
		scanf("%d", p+i);//p+i == &arr[i]
	}

	//输出10个值
	for (i = 0; i < sz; i++)
	{
		printf("%d ", i[arr]);//p[i]  arr[i]  *(arr+i)
	}

	return 0;
}

 arr[i]==>*(arr+i)等价

1.数组就是数组,是一块连续的空间(数组的大小和数组元素个数和元素类型都有关系)
2.指针(变量)就是指针(变量),是!一个变量(4/8个字节)

数组与指针的联系:

3.数组名是地址,是首元素的地址
4.可是使用指针来访问数组

3.一维数组传参的本质

 打印的值为1,是指针变量的大小,不是数组的大小

数组传参的时候,形参是可以写成数组的形式的
但是本质上还是指针变量

void Print(int arr[10])//int* arr
{
	int sz = sizeof(arr) / sizeof(arr[0]);//得不到元素个数的,算出来的是指针变量的大小
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

void Print(int* p,int sz) //应该是指针
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
}

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	Print(arr, sz);//arr 数组名就是数组首元素的地址

	//sizeof(arr)
	//&arr
	return 0;
}

1. 数组传参的本质是传递了数组首元素的地址,所以形参访问的数组和实参的数组是同一个数组的。

2.形参的数组是不会单独再创建数组空间的,所以形参的数组是可以省略掉数组大小的。

总结:一维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。

4 .冒泡排序

 冒泡排序的核心思想:就是两两相邻的元素进行比较。

 图示:

代码如下

升序
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-1-i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;
			}
		}
		if (flag == 1)
		{
			break;
		}
	}
}

void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	//排序
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	//打印
	print_arr(arr, sz);
	return 0;
}

 

 避免已经排序结束了,但是还在循环

 

 5.二级指针

int main()
{
	int a = 10;
	int* p = &a;//p就是一级指针

	int * * pp = &p;

	int** * ppp = &pp;
	int**** pppp = &ppp;
	//.....
	return 0;
}

 

 

 解引用

6.指针数组

指针数组是数组还是指针?

是数组!
eg:好孩子,主语是孩子

我们类比一下,整型数组,是存放整型的数组,字符数组是存放字符的数组。
那指针数组呢?是存放指针的数组。

 

7.指针数组模拟二维数组

 并不是真的二维数组,只是模拟出来的 

 图解:

parr[]是访问parr数组的元素,parr[i]找到的数组元素指向了整型一维数组,parr[i][j]就是整型一维数组中的素。

上述的代码模拟出二维数组的效果,实际上并非完全是二维数组,因为每一行并非是连续的。

希望对你有帮助!加油各位!!

每一次努力都是不凡的历练,每一点进步都是值得庆祝的胜利。你正在创造属于自己的辉煌,相信自己,一切皆有可能。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值