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

【C语言】指针初阶2.0版本

这篇博文我们来继续学习指针的其他内容

在这里插入图片描述

指针2.0

  • 传值调用与传址调用
    • 传值调用
    • 传址调用
  • 一维数组与指针
    • 理解数组名
    • 使用指针
    • 深入理解一维数组
  • 二级指针
  • 指针数组
  • 二维数组与指针

传值调用与传址调用

在开始之前,我们需要先了解这个概念,后面才能够正常的学习

传值调用

int add(int x, int y)
{return x + y;
}
int main()
{int a = 10;int b = 20;int c = add(a, b);printf("%d", c);return 0;
}

经典的传值调用,只需要传值即可,没有过多的要求,但如果我们的要求是将ab互换大小,再用这样的代码就行不通了

void ecn(int x, int y)
{int tmp = x;x = y;y = tmp;
}
int main()
{int a = 10;int b = 20;ecn(a, b);printf("a = %d\n", a);printf("b = %d\n", b);return 0;
}

在这里插入图片描述
我们发现,这样做交换不了两者的值,是因为形参是实参的一份临时拷贝,形参也是有地址的,改变形参影响不了实参,这时我们只能进行传址调用

传址调用

void ecn(int* x,int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
int main()
{int a = 10;int b = 20;ecn(&a, &b);printf("a = %d\n", a);printf("b = %d\n", b);return 0;
}

在这里插入图片描述
这样就能进行调换了,改变实参的值

一维数组与指针

理解数组名

int arr[5] = {1,2,3,4,5};

当我们想要访问arr数组时,我们有一下几种方法

int i = arr[0];
int* p = &arr[0];
int* p = arr;

第一种不必多说,利用访问下标操作符对数组进行访问。第二、三种是我们上一篇文章说的(可移步上一篇:指针初阶),通过指针对数组进行访问,arr与&arr[0]是一样的,都是数组的首元素地址
那我们可能会有疑问了:那&arr是什么样的呢,跟这两个也一样吗?下面我们用编译器来测试下,顺便证明一下第二三种是一样的
打印它们的地址

#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5 };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[5] = { 1,2,3,4,5 };printf("%d\n", sizeof(arr));return 0;
}

在这里插入图片描述
如果它们都相同,那么sizeof(arr)与sizeof(arr【0】)应该相同,那应该在32位下为4,只有整个数组的大小才为20,这与我们之前所看到的相悖,我们最后来看一下区别在哪

#include <stdio.h>
int main()
{int arr[5] = { 1,2,3,4,5 };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+1跟另外两个不同,地址加了20,而另外两个加了4;正如我们所想,arr确实代表着一个数组,但&arr取的是首元素的地址,整个数组是一个整体

使用指针

#include <stdio.h>
int main()
{int arr[5] = { 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]);//这里*(p+i)=p[i]}return 0;

数组元素的访问在编译器处理的时候转换成⾸元素的地址+偏移量求出元素的地址,然后解引⽤来访问。

深入理解一维数组

当我们写函数的时候,如果想要改变数组的内容:⼀维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。
其实这个也是想当然的,因为数组可以用指针来表示,二者等同,那么取而代之肯定也是非常正确的,因为数组的本质就是指针

二级指针

二级指针的概念也很简单,就是存放一级指针的地址的指针

int main()
{int i = 10;int* pi = &i;int** ppi = &pi;return 0;
}
*ppi = pi;
**ppi = i;

同理,存放二级指针地址的就是三级指针

指针数组

指针数组就是存放指针的数组,里边每个元素都是地址

int* arr1;//里边的指针类型全部为int*
char* arr2;//里边的指针类型全部为char*

二维数组与指针

#include <stdio.h>
int main()
{int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 2,3,4,5,6 };int arr3[5] = { 3,4,5,6,7 };int* parr[3] = { arr1, arr2, arr3 };//我们一般把p作为指针变量,后面加上arr表示是数组指针变量,有关于数组指针变量的知识我们下期再分享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;
}

我们看到很熟悉的parr[ i ][ j ]的形式,这其实就是二维数组的真正形态,在运行时二维数组也是要先变成指针的形式再进行运算的,所以说数组的本质是指针

这篇2.0就到这里了,感谢阅读
在这里插入图片描述

相关文章:

  • vue如何使用冻结对象提升代码效率及其原理解析
  • Linux中systemv共享内存
  • 亿道信息新品EM-T195轻薄型工业平板,隆重登场!
  • Linux下检查端口占用
  • 3.1log | 62.不同路径,63. 不同路径 II,343. 整数拆分,96.不同的二叉搜索树
  • 【考研数学】零基础备考全年计划
  • 单调栈的理解
  • Facebook的元宇宙实践:数字化社交的新前景
  • 4.1.CVAT——目标检测的标注详细步骤
  • 【HbuilderX】 uniapp实现 android申请权限 和 退出app返回桌面
  • 加密与安全_探索口令加密算法(PBE)
  • 【应用多元统计分析】--数据矩阵及R语言表示
  • Flink CDC 3.0 Starrocks建表失败会导致任务卡主!
  • 吸猫毛空气净化器哪个好?推荐除猫毛效果好宠物空气净化器品牌
  • paper-ai :搜索真实文献并生成引用真实文献的AI论文
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • Cookie 在前端中的实践
  • CSS实用技巧干货
  • php中curl和soap方式请求服务超时问题
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • v-if和v-for连用出现的问题
  • 关于for循环的简单归纳
  • 基于遗传算法的优化问题求解
  • 前嗅ForeSpider教程:创建模板
  • 我这样减少了26.5M Java内存!
  • 自动记录MySQL慢查询快照脚本
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 交换综合实验一
  • (27)4.8 习题课
  • (4)(4.6) Triducer
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (搬运以学习)flask 上下文的实现
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (四)Controller接口控制器详解(三)
  • (万字长文)Spring的核心知识尽揽其中
  • (五)网络优化与超参数选择--九五小庞
  • (一)插入排序
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)原始图像数据和PDF中的图像数据
  • .net(C#)中String.Format如何使用
  • /dev/sda2 is mounted; will not make a filesystem here!
  • @ModelAttribute 注解
  • @RequestParam,@RequestBody和@PathVariable 区别
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [2019.3.20]BZOJ4573 [Zjoi2016]大森林
  • [ACM] hdu 1201 18岁生日
  • [c]扫雷
  • [CSS] - 修正IE6不支持position:fixed的bug
  • [Fri 26 Jun 2015 ~ Thu 2 Jul 2015] Deep Learning in arxiv
  • [hdu2196]Computer树的直径
  • [IE技巧] IE 中打开Office文件的设置
  • [LeetBook]【学习日记】获取子字符串 + 颠倒子字符串顺序
  • [Linux打怪升级之路]-信号的保存和递达
  • [NISACTF 2022]level-up
  • [No000010F]Git8/9-使用GitHub