C语言——深入解析C语言指针:从基础到实践从入门到精通(三)

🏡润下个人主页
🔥个人专栏 : 《C语言基础》

🏔️山高万仞,只登一步!



文章目录

前面简单介绍指针访问数组,本节接介绍指针和数组的关系,如何用指针更高效,更快捷的访问数组!

一.数组名的理解

在前面我们在使用指针访问数组的时候通常用:

c 复制代码
int arr[10] = { 1,2,3,4,5,6,7,8,10 };
int* p = &arr[0];

使用&arr0的方式拿到了数组的首元素地址,但是也可以用arr获取首元素地址

c 复制代码
#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    =%p\n", arr);
	return 0;
}


发现数组名就是数组首元素(第一个元素)地址

如果数组名是首元素地址的话,用sizeof计算出来的地址大小应该是4/8

但是之前在用sizeof计算数组大小的时候,arr作为表达式时候计算的出来的是整个数组的大小

c 复制代码
#include<stdio.h>
int main()
{
	int arr[5] = { 1,2,3,4,5 };
	printf("%d\n", sizeof(arr));
	return 0;
}

输出的结果是20,如果是数组地址输出的应为4/8;

其实:数组名是首元素地址是正确的,但是有两个例外

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

&数组名,表示为整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的
除此之外:数组名都表示数组首元素的地址

实例

c 复制代码
#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     =%p\n", arr);//首元素地址
	printf("&arr    =%p\n", &arr);//数组的地址
	return 0;
}

但是发现输出的结果都一样,那么数组的地址和数组首元素的地址到底有什么区别呢?
arr与&arr

c 复制代码
#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;
}

&arr0+1相差4个字节,arr和arr+1相差4个字节,他们都是首元素的地址,+1跳过一个元素

&arr和&arr+1相差40个字节,因为&arr是数组的地址,+1跳过整个数组
指针类型决定±1跳过多少字节

二.使用指针访问数组

指针访问数组

c 复制代码
#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	for ( i = 0; i <sz; i++)
	{
		scanf("%d", p + i);
	}
	for ( i = 0; i <sz; i++)
	{
		printf("%d ", *(p + i));
	}
	return 0;
}

由前面介绍知道,数组名arr是首元素的地址,用arr赋值给p,arr等价于p,那么我们可以用arr访问数组,是否也可以用pi访问数组

c 复制代码
#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	for (i = 0; i < sz; i++)
	{
		scanf("%d", arr+ i);
	}
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));
	}
	return 0;
}


结论

可以把下标引用操作符 当作加号 +可以进行交换律
指针让我们对空间多了一种访问方式

三.一维数组传参的本质

数组是无法在函数内部计算数组元素的个数的

c 复制代码
#include<stdio.h>
void test(int arr[])
{
	int sz2 = sizeof(arr) / sizeof(arr[0]);
	printf("sz2   =%d\n", sz2);
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("sz1   =%d\n", sz);
	test(arr);
	return 0;
}

在test函数中没有正确得出元素个数

数组名是首元素地址,在作为参数传递的过程中传递的是数组名,实际上传递 的是数组首元素的地址 。因此函数内部计算的是地址的大小而不是数组的个数。函数参数部分是指针(地址),所以在函数内部是无法求数组元素个数的

因为传递的是指针,所以函数参数部分也可以写成指针的形式

c 复制代码
#include<stdio.h>
void test1(int arr[])
{
	printf("%d\n", sizeof(arr));
}
void test2(int *arr)
{
	printf("%d\n", sizeof(arr));
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("sz1   =%d\n", sz);
	test1(arr);
	test2(arr);
	return 0;
}

如果想要在函数内打印数组可以写成:

c 复制代码
#include<stdio.h>
void test(int* arr, int sz)
{
	int i = 0;
	for ( i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("sz1   =%d\n", sz);
	test(arr,sz);
	return 0;
}

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

四.冒泡排序

排序思想:

相邻两个元素进行比较

c 复制代码
#include<stdio.h>
void Bubble_sort(int* arr, int sz)
{
	int i = 0;
	for ( i = 0; i < sz-1; i++)
	{
		int j = 0;
		for ( j= 0; j< sz-1-j; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
int  main()
{
	int arr[10] = { 0 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for ( i = 0; i < sz; i++)
	{
		scanf("%d", &arr[i]);
	}
	Bubble_sort(arr, sz);
	for ( i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

优化:

c 复制代码
#include<stdio.h>
void Bubble_sort(int* arr, int sz)
{
	int flag = 1;
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - j; 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)//如果flag==1说明没有进行交换,是有序
		{
			break;
		}
	}
}
int  main()
{
	int arr[10] = { 0 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i < sz; i++)
	{
		scanf("%d", &arr[i]);
	}
	Bubble_sort(arr, sz);
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

五.二级指针

指针变量也是变量,是变量就有地址,指针变量用二级指针来存放

c 复制代码
#include<stdio.h>
int main()
{
	int a = 10;
	int* pa = &a;
	int** ppa =&pa;
	printf("%d\n", **ppa);
	return 0;
}

由图会发现ppa也有地址,也可以放在指针变量中,多级指针但是一般情况下不会超过二级指针

六.指针数组

指针数组还是数组 可以类比🚩:整型数组存放的是整数,字符型数组存放的是字符。

那么指针数组存放的是指针

数组类型 存放内容
整型数组 整数
字符型数组 字符
指针数组 指针


实例

c 复制代码
#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	int c = 30;
	int* arr[3] = { &a,&b,&c };
	return 0;
}

一个个创建指针变量太麻烦,可以创建一个指针数组里面存放指针变量

七.指针数组模拟和实现

c 复制代码
#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	int* parr[3] = { arr1,arr2,arr3 };
	int i = 0;
	int j = 0;
	for ( i = 0; i < 3; i++)
	{
		for (j = 0;j < 5;j++)
		{
			printf("%d ", parr[i][j]);
		}
		printf("\n");
	}
	return 0;
}


注:二维数组是是连续存放的

总结

相关推荐
red_redemption3 分钟前
自由学习记录(205)
学习
AI行业学习3 分钟前
Notepad++ 官方纯净下载+完整安装教程(Windows)【2026.7.5】
开发语言·windows·python·前端框架·html·notepad++
卡梅德生物科技小能手7 分钟前
卡梅德生物科普CD80(B7-1):免疫系统的“双面间谍”
经验分享·深度学习·生活
cmes_love8 分钟前
如何下载沪深股票市场的行情数据,包括委托、成交、订单薄、沪深股票、etf、可转债、指数五档订单薄数据,买一到买五、卖一到卖五历史行情数据笔记
大数据·笔记
摇滚侠13 分钟前
Apache Skywalking 实战 阅读笔记 第二章
笔记·apache·skywalking
前端百草阁16 分钟前
JavaScript 设计模式(23 种)
开发语言·前端·javascript·设计模式
EntyIU20 分钟前
Java NIO 实战
java·开发语言·nio
BomanGe124 分钟前
NSK微型精密滚珠丝杠W0801MA技术指南
经验分享·规格说明书
chushiyunen36 分钟前
word使用笔记(二)、邮件合并(模板套用)
笔记·word
浩瀚之水_csdn41 分钟前
Python 3 网络编程详解:从原理到实战
开发语言·网络·python