当前位置: 首页 > news >正文

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


🏡润下:个人主页

  🔥个人专栏: 《C语言基础》

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

在这里插入图片描述
在这里插入图片描述

文章目录

  • 一.数组名的理解
  • 二.使用指针访问数组
  • 三.一维数组传参的本质
  • 四.冒泡排序
  • 五.二级指针
  • 六.指针数组
  • 七.指针数组模拟和实现
  • 总结

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

一.数组名的理解

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

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

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

#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作为表达式时候计算的出来的是整个数组的大小

#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中单独放数组名,表示为整个数组计算的是整个数组的大小,单位是字节
&数组名,表示为整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的
除此之外:数组名都表示数组首元素的地址

实例

#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

#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;
}

在这里插入图片描述
&arr[0]+1相差4个字节,arr和arr+1相差4个字节,他们都是首元素的地址,+1跳过一个元素
&arr和&arr+1相差40个字节,因为&arr是数组的地址,+1跳过整个数组
指针类型决定±1跳过多少字节

二.使用指针访问数组

指针访问数组

#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访问数组,是否也可以用p[i]访问数组

#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;
}

在这里插入图片描述
结论
在这里插入图片描述
可以把下标引用操作符 [ ] 当作加号 +可以进行交换律
指针让我们对空间多了一种访问方式

三.一维数组传参的本质

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


#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函数中没有正确得出元素个数
数组名是首元素地址,在作为参数传递的过程中传递的是数组名,实际上传递的是数组首元素的地址。因此函数内部计算的是地址的大小而不是数组的个数。函数参数部分是指针(地址),所以在函数内部是无法求数组元素个数的
因为传递的是指针,所以函数参数部分也可以写成指针的形式

#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;
}

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

#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;
}

在这里插入图片描述
总结:一维数组传参,形参部分可以写数组的形式,也可以写成指针的形式

四.冒泡排序

排序思想:
相邻两个元素进行比较

#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;
}

优化:

#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;
}

五.二级指针

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

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

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

六.指针数组

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

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

在这里插入图片描述
实例

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

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

七.指针数组模拟和实现

#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;
}

在这里插入图片描述
在这里插入图片描述

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

总结

在这里插入图片描述

http://www.dtcms.com/a/478397.html

相关文章:

  • 威科夫、缠论和订单流如何进行融合
  • 电影网站建设视频教程中级经济师考试报名
  • Spring AI 文档ETL实战:集成text-embedding-v4 与 Milvus
  • Java 包装类:自动拆箱 / 装箱与 128 陷阱
  • 行业 观察
  • 59网站一起做网店淘宝网站咋做
  • 那个公司做的外贸网站好wordpress可视化函数
  • LabelImg和Labelme:目标检测和图像分割的标注工具
  • 国外素材网站推荐linux主机上传网站
  • 开源php公司网站wordpress语音搜索
  • UE 如何迁移 DerivedDataCache 路径,避免 C 盘因海量模型缓存爆盘
  • 支付宝小程序 SEO 实战:鲜花送达类小程序抢占搜索流量指南
  • 小吉快检BL-08plus:推动动物疫病早发现、早防控的科技引擎
  • 个人网站如何搭建上海工商网官网登录
  • wordpress做小说网站网站建设 sql 模版
  • 从HIDL到AIDL:Android HAL架构的演进与抉择
  • Redis-stream、bitfield类型
  • [Python脚本]快速检测两个文件夹之间的视觉重复图片
  • 【Postgresql】PG版本升级,PG14到PG15,且数据迁移
  • 数据库原理与设计
  • iis7配置thinkphp网站做海报的网站有哪些内容
  • 【开题答辩全过程】以 博客网站为例,包含答辩的问题和答案
  • 解决 MySQL `MAX(IF())` 中 `table.column` 有值但显示 `‘default‘` 的问题
  • 如何加快门户网站建设wordpress 资源下载插件
  • 视频播放器 v12.1.357 | 4K顶级播放器,内置了视频下载器,可下载推特~脸书等国外视频
  • 路径总和---超全详细解
  • 【深入浅出PyTorch】--6.2.PyTorch进阶训练技巧2
  • JS - 运算符
  • Ethical use of recommender systems|推荐系统的道德使用
  • 网站建设 全网推广建网站的域名