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

「1」指针进阶——详解

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀 

目录

🐰指针的回顾

🐰字符指针

🐰指针数组

🌸模拟二维数组(整形)

🐰数组指针

🌸数组指针和指针数组的区分

🌸&数组名和数组名的区别

🌸数组指针p,*p等价于arr,*p就是数组名

🌸数组指针的使用

🌸数组参数和指针参数

🐰函数指针-指向函数的指针

🌸函数指针数组


🐰指针的回顾

1.指针是内存中一个最小单元的编号,也就是地址

2.平时口语上所说的指针,通常指的是指针变量,是用来存放地址的变量

3.把内存划分为一个个的内存单元,这个内存单元大小是1字节,从概念上讲:编号 == 地址 == 指针

指针变量:

我们可以通过& (取地址操作符) 取出变量的内存起始地址,把地址可以存放到一个变量中,这个变量就是指针变量

4.指针大小(4字节 32位/8字节 64位)

🐰字符指针

#include<stdio.h>
int main()
{char ch='w';char* pc=&ch;const char* p="abcdef";//"abcdef",是把字符串的首地址放到p中//"abcdef"是常量字符串,是不可以修改的char arr[]="abcdef";//"abcdef",这里的arr的值是可以修改的char *pa=arr;*pa='w';printf("%s\n",arr);//修改的结果为wbcdefreturn 0;
}

‼️注:常量字符串在内存中只保存一份!!!

#include<stdio.h>
int main()
{char str1[]="abcdef";char str2[]="abcdef";char* str3="abcdef";//保存的就是常量字符串char* str4="abcdef";//保存的就是常量字符串if(str1==str2)//数组保存的字符串是变量,所以str1!=str2{printf("str1==str2\n");}else{printf("str1!=str2\n");}if(str3==str4)//常量字符串在内存中只保留一份,所以str3==str4{printf("str3==str4\n");}else{printf("str3!=str4\n");}return 0;
}

结果为:
str1!=str2

str3==str4

🐰指针数组

字符数组-存放字符的数组
char arr[10];
整形数组-存放整形的数组
int arr[10];
指针数组-存放的就是指针
char* arr[10];
int* arr[10];
#include<stdio.h>
int main()
{char* arr[]={"abc","bcd","edf"};//指针数组,保存了三个字符串的首地址for(int i=0;i<3;i++){printf("%s\n",arr[i]);}return 0;
}
结果为:

abc

bcd

edf

🌸模拟二维数组(整形)

#include<stdio.h>
int main()
{int arr1[]={1,2,3,4,5};int arr2[]={1,2,3,4,5};int arr3[]={1,2,3,4,5};int arr4[]={1,2,3,4,5};int* arr5[]={arr1,arr2,arr3,arr4};for(int i=0;i<4;i++){for(int j=0;j<5;j++){printf("%d",*(arr5[i]+j));//printf("%d\n",arr5[i][j]);//结果一样}printf("\n");}return 0;
}

结果为:

12345

12345

12345

12345

🐰数组指针

整形指针-指向整形的指针
int a=10;
int* P=&a
字符指针-指向字符的指针
char ch='w';
char* pc=&ch;
数组指针-指向数组的指针
int arr[10];
&arr就是数组的地址
int (*pa)[10]=&arr;
char arr[10];
char(*pc)[10]=&arr
int* arr[5];
int* (*pa)[5]=&arr//这个数组指针指向的是arr这个指针数组

🌸数组指针和指针数组的区分

指针数组->存放指针的数组
数组指针->是一种指向数组的指针-存放的是数组的地址

🌸&数组名和数组名的区别

数组名是数组首元素地址
sizeof(数组名)--这个时候表示的不是首元素的首地址,计算的整个数组的大小
&数组名--这里的数组名表示整个数组,取出的是整个数组的地址,从地址角度看和数组首元素的地址一样,他们的类型不一样
#include<stdio.h>
int main()
{int arr[10]={0};printf("arr=%p\n",arr);//数组首元素的地址printf("arr+1=%p\n",arr+1);//数组第二个元素的地址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);//数组第最后一个元素的下一个的地址int(*p)[10]=&arr;//数组指针保存整个数组的地址return 0;
}

结果

r=0x7ffeefbff3c0
arr+1=0x7ffeefbff3c4
&arr[0]=0x7ffeefbff3c0
&arr[0]+1=0x7ffeefbff3c4
&arr=0x7ffeefbff3c0
&arr+1=0x7ffeefbff3e8

🌸数组指针p,*p等价于arr,*p就是数组名

#include<stdio.h>
int main()
{int arr[10]={1,2,3,4,5,6,7,8,9,10};int (*p)[10]=&arr;for(int i=0;i<10;i++){printf("%d ",*((*p)+i));//*p等价于arr,*p就是数组名}return 0;
}
结果为:

1 2 3 4 5 6 7 8 9 10

🌸数组指针的使用

#include<stdio.h>
void print(int (*arr)[5],int r,int c)
{for(int i=0;i<r;i++){for(int j=0;j<c;j++){printf("%d ",*(*(arr+i)+j));//arr+i==&arr[i]//printf("%d ",arr[i][j]);}}
}
int main()
{//二维数组的数组名,也表示首元素地址//二维数组的首元素是第一行的地址,是一个一维数组的地址int arr[3][5]={1,2,3,4,5,6,7,8,9,10};print(arr,3,5);return 0;
}

结果为:
1 2 3 4 5 6 7 8 9 10 0 0 0 0 0

二维数组arr

int (*p)[10]=&arr;
p等价于arr
arr=&arr[i]
arr[i]=&arr[i][0]
分析代码
int arr[5];
int *parr1[10];//指针数组
int (*parr2)[10];//数组指针
int (*parr3[10])[5];//数组中存放的数组指针

🌸数组参数和指针参数

一维数组传参
一维数组传参,形参可以是数组,可以是指针
二维数组传参
参数可以是指针,可以是数组,如果是指针,传过去的是第一行的地址
函数形参的设计只能省略第一个[]的数字,因为一个二维数组,可以不知道有对少行,但是必须知道一行有多少元素
一级指针传参
当一个函数的参数部分为一级指针的时候,函数能接收什么参数
数组,指针
二级指针传参
当一个函数的参数部分为二级指针的时候,函数能接收什么参数
二级指针变量,一级指针的地址,指针数组

🐰函数指针-指向函数的指针

函数指针存放的是函数的地址,函数也是有地址的
‼️注:函数名和取地址函数名 是一样的
#include<stdio.h>
int Add(int x,int y)
{return x+y;
}
//函数是存在地址
int main()
{printf("%p\n",&Add);//0x100003f40printf("%p\n",Add);//0x100003f40int (*pf)(int,int)=Add;//pf就是函数指针int ret=(*pf)(3,5);//函数指针的调用int rat=pf(3,5);//*pf和pf等价//这里的*没有实际的意义,可以不要pf(3,5),可以多加(**pf)(3,5),都不影响结果,*pf)(3,5)是为了方便理解printf("%d %d\n",ret,rat);
}

结果为:

0x100003ef0

0x100003ef0

8 8

🌸函数指针数组

数组的每个元素是一个函数指针
这是利用switch()语句制作的两位数计算器
#include<stdio.h>
int Add(int x,int y)
{return x+y;
}
int Sub(int x,int y)
{return x-y;
}
int Mul(int x,int y)
{return x*y;
}
int Div(int x,int y)
{return x/y;
}
void menu(void)
{printf("****    两位数的计算器     ****\n");printf("****    1.Add   2.Sub   ****\n");printf("****    3.Mul   4.Div   ****\n");printf("****    0.exit          ****\n");
}
int main()
{int input=0;do{menu();printf("请选择\n");scanf("%d",&input);int x=0,y=0,ret=0;switch(input){case 1:printf("请输入两个操作数\n");scanf("%d %d",&x,&y);ret=Add(x,y);printf("%d\n",ret);break;case 2:printf("请输入两个操作数\n");scanf("%d %d",&x,&y);ret=Sub(x,y);printf("%d\n",ret);break;case 3:printf("请输入两个操作数\n");scanf("%d %d",&x,&y);ret=Mul(x,y);printf("%d\n",ret);break;case 4:printf("请输入两个操作数\n");scanf("%d %d",&x,&y);ret=Div(x,y);printf("%d\n",ret);break;default:printf("输入错误\n");}}while(input);
}

结果为:

****      两位数的计算器     ****

****      1.Add   2.Sub        ****

****      3.Mul   4.Div         ****

****      0.exit                      ****

请选择

1

请输入两个操作数

3 8

11

这种算法,太冗余了,不够简洁
这是利用函数指针数组制作的两位数计算器
#include<stdio.h>
int Add(int x,int y)
{return x+y;
}
int Sub(int x,int y)
{return x-y;
}
int Mul(int x,int y)
{return x*y;
}
int Div(int x,int y)
{return x/y;
}
void menu(void)
{printf("****    两位数的计算器     ****\n");printf("****    1.Add   2.Sub   ****\n");printf("****    3.Mul   4.Div   ****\n");printf("****    0.exit          ****\n");
}
int main()
{int input=0;do{int x=0,y=0;menu();printf("请选择\n");scanf("%d",&input);printf("请输入两个操作数\n");scanf("%d %d",&x,&y);int (*pf[5])(int,int)={0,Add,Sub,Mul,Div};//这里之所以数组元素给了5个,是为了与菜单对应起来if(input<5&&input>=0){int ret=(*pf[input])(x,y);printf("%d\n",ret);}else if(input==0){printf("计算结束\n");break;}else{printf("输入错误\n");}}while(input);
}

结果为:

****      两位数的计算器     ****

****      1.Add   2.Sub        ****

****      3.Mul   4.Div         ****

****      0.exit                      ****

请选择

1

请输入两个操作数

3 8

11

这种算法,很简洁,逻辑更清晰。

🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸      

相关文章:

「1」指针进阶——详解

&#x1f680;&#x1f680;&#x1f680;大家觉不错的话&#xff0c;就恳求大家点点关注&#xff0c;点点小爱心&#xff0c;指点指点&#x1f680;&#x1f680;&#x1f680; 目录 &#x1f430;指针的回顾 &#x1f430;字符指针 &#x1f430;指针数组 &#x1f338;模…...

JS语法让人困惑的点 “==与===”

在JS中有很多神奇的语法&#xff0c;非常让人困惑&#xff0c;我们就先一一道来&#xff0c;相信你在开发中或多或少都踩过这些坑&#xff0c;或者让人无法理解。 今天我们就来说下【】和【】 这题对于很多没有系统学过前端开发的技术人员来说&#xff0c;算个重点&#xff0c…...

《狂飙》壁纸大嫂如此惊艳,做成日历壁纸天天看

兄弟们&#xff0c;今年的反腐大剧狂飙都有看吗 &#xff1f; 话说&#xff0c;名字虽然叫狂飙&#xff0c;但是全剧只有有田一个人在狂飙&#xff01; 当然&#xff0c;有田虽然亮眼&#xff0c;但是毕竟是个糟老头子&#xff0c;正经人谁看有田啊&#xff0c;当然是看大嫂了…...

手机照片删除了怎么恢复

手机照片删除了怎么恢复?喜欢拍照的小伙伴&#xff0c;都会不定期删除手机上的照片&#xff0c;因为这些爱拍照的人&#xff0c;手机中会存储着很多照片&#xff0c;删除照片是必然的&#xff0c;但在手机删除照片时&#xff0c;如果是一张一张删除太麻烦了&#xff0c;就直接…...

maven pom.xml 依赖的scope属性

maven pom.xml 依赖的scope属性 compile 适用范围 编译期、测试期、运行期 作用 从中央仓库拉取依赖到本地&#xff0c;并编译 打包到结果包中 runtime 适用范围 测试期、运行期 作用 runtime 用在 Class.forName(“com.mysql.jdbc.Driver”) 时&#xff0c;compile 编…...

git 的使用方法 (下 - 远程仓库和图形化)

目录前言&#xff1a;一、什么是协同开发二、Gitee 使用协同开发1. 首先注册一个码云账号2. 新建一个仓库3. 根据下图把新建仓库设置为开源4. 在远端合并分支的方法5. 链接 git 远程6. 提交&#xff08;同步&#xff09;远程7. 远程拉取至本地8. 远程分支三、git 图形化的使用1…...

Java基础:拼图小游戏

涉及到的知识: 1.图形用户接口GUI(Graphical User Interface)用图形化的方式显示操作界面 两个体系: AWT包和Swing包 2.界面会用到JFrame类 3.界面中的菜单会用到JMenuBar, JMenu, JMenuItem 4.添加图片 在设置完JLabel的location之后还需要获得展示内容的窗体, 通过setLay…...

一个跟蘑菇结缘的企业老板

记得那是一个很久以前的一家公司了董事长办公室里中的大型盆栽里面长了一个蘑菇董事长认为是祥瑞每天都会浇水后来一个新来的保洁阿姨以为杂草啥的给他掰掉扔垃圾桶了董事长第二天来浇水的时候发现没了就问谁动了他的蘑菇问道之后就跑到楼道大垃圾桶那里把蘑菇找回来种在花盆里…...

【Leetcode 剑指Offer】第 4 天 查找算法(简单)

查找剑指 Offer 03. 数组中重复的数字剑指 Offer 53 - I. 在排序数组中查找数字 I二分法题目链接剑指 Offer 03. 数组中重复的数字 题&#xff1a;在一个长度为 n 的数组 nums 里的所有数字都在 0&#xff5e;n-1 的范围内。数组中某些数字是重复的&#xff0c;但不知道有几个数…...

Jenkins利用docker部署vue项目

Jenkins利用docker部署vue项目一、环境准备1、安装docker2、安装nodejs3、安装cnpm与配置淘宝镜像4、jenkins安装nodejs插件二、jenkins以vue项目1、全局参数配置2、源码配置3、构建环境4、构建三、构建项目四、访问一、环境准备 本次jenkins与部署vue项目在同一台机器&#x…...

【Linux】如何将ntfs硬盘挂载到home目录下并具有读写权限

步骤1. 查看当前挂载的硬盘及其挂载点2. 查看需要挂载到home下的磁盘类型信息3. 在home下新建一个空的文件夹作为该磁盘的新挂载点4. 以ntfs类型的硬盘为例&#xff0c;使用mount命令进行挂载5. 问题1&#xff1a;进程占用了磁盘6. 问题2&#xff1a;磁盘权限为只读的7. 永久挂…...

拖拽删除元素、拖拽排序、拖拽预览图片和拖拽移动元素

介绍 HTML5 提供了专门的拖拽与拖放的 API&#xff0c;目前各浏览器都已支持&#xff0c;包括 IE。HTML 拖放&#xff08;Drag and Drop&#xff09;接口使应用程序能够在浏览器中使用拖放功能。例如&#xff0c;用户可使用鼠标选择可拖拽&#xff08;draggable&#xff09;元素…...

yarn的global安装命令不生效

问题 yarn全局安装某个依赖完成之后&#xff0c;但依赖没有生效&#xff0c;一般有两种情况导致的。 解决思路 1.yarn命令问题 yarn在全局安装某个依赖时&#xff0c;global要紧接在yarn之后&#xff0c;然后才是add yarn global add xxxx如果出现global在add之后&#xff…...

如何发布自己的npm包?

1 文件组成 package.json文件components文件css样式文件index.js文件 2 package.json配置 description&#xff1a;描述title&#xff1a;题目keywords&#xff1a;搜索关键词typings&#xff1a;指定TypeScript的入口文件main&#xff1a;加载的入口文件module&#xff1a;…...

达梦数据库 闪回查询

当用户操作不慎导致错误的删改数据时&#xff0c;非常希望有一种简单快捷的方式可以恢复数据。闪回技术&#xff0c;就是为了用户可以迅速处理这种数据逻辑损坏的情况而产生的。 闪回技术主要是通过回滚段存储的 UNDO 记录来完成历史记录的还原。如果提交了&#xff0c;还没有…...

java基础学习 day44(多态的优点和劣势)

1. 多态的优势 在多态形式下&#xff0c;右边对象可以实现解耦合&#xff08;即之后的代码与右边的子类对象不绑定&#xff0c;在更改子类对象后&#xff0c;之后的代码仍可以使用&#xff09;&#xff0c;便于扩展和维护在定义方法的时候&#xff0c;使用父类型作为参数&…...

Guna UI WinForms 2.0.4.4 Crack

Guna.UI2 WinForms is the suite for creating groundbreaking desktop app UI. It is for developers targeting the .NET Windows Forms platform. 50 多个 UI 控件 具有广泛功能的综合组件可帮助您开发任何东西。 无尽的定制 只需拖放即可创建视觉效果命令和体验。 出色的…...

零售航母沃尔玛公布业绩:喜忧参半

2月21日美股盘前&#xff0c;零售巨无霸沃尔玛公布了截至1月的2023财年第四季度业绩报告。财报中不乏可圈可点之处&#xff0c;但是利润迎来六年首降&#xff0c;新财年的利润指引要也比预期低很多&#xff0c;可以说喜忧参半。 一、Q4业绩可圈可点 营收方面&#xff1a;在本…...

Python学习笔记丨while、for、if循环结构基础知识与易错点

Python流程控制 本篇笔记的主要内容是&#xff1a;条件控制和循环控制&#xff0c;包括if语句、while语句、for语句等。 Python条件控制 if (m : 1) > 0: # :是海象运算符&#xff0c;用于在函数内部为变量赋值 print("ok")ok 通过if语句来判断条件是否成立&am…...

【ROS学习笔记1】ROS快速体验输出Hello World

【ROS学习笔记1】ROS快速体验输出Hello World 文章目录【ROS学习笔记1】ROS快速体验输出Hello World1.1 ROS快速体验1.1.1 Hello World快速实现简介1.1.2 Hello World的C实现1.1.3 Hello World的Python实现写在前面&#xff0c;本系列笔记参考的是AutoLabor的教程&#xff0c;具…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...