「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!=str2str3==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]=&arrint* 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=0x7ffeefbff3c0arr+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等价于arrarr=&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」指针进阶——详解
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀 目录 🐰指针的回顾 🐰字符指针 🐰指针数组 🌸模…...
JS语法让人困惑的点 “==与===”
在JS中有很多神奇的语法,非常让人困惑,我们就先一一道来,相信你在开发中或多或少都踩过这些坑,或者让人无法理解。 今天我们就来说下【】和【】 这题对于很多没有系统学过前端开发的技术人员来说,算个重点,…...
《狂飙》壁纸大嫂如此惊艳,做成日历壁纸天天看
兄弟们,今年的反腐大剧狂飙都有看吗 ? 话说,名字虽然叫狂飙,但是全剧只有有田一个人在狂飙! 当然,有田虽然亮眼,但是毕竟是个糟老头子,正经人谁看有田啊,当然是看大嫂了…...
手机照片删除了怎么恢复
手机照片删除了怎么恢复?喜欢拍照的小伙伴,都会不定期删除手机上的照片,因为这些爱拍照的人,手机中会存储着很多照片,删除照片是必然的,但在手机删除照片时,如果是一张一张删除太麻烦了,就直接…...
maven pom.xml 依赖的scope属性
maven pom.xml 依赖的scope属性 compile 适用范围 编译期、测试期、运行期 作用 从中央仓库拉取依赖到本地,并编译 打包到结果包中 runtime 适用范围 测试期、运行期 作用 runtime 用在 Class.forName(“com.mysql.jdbc.Driver”) 时,compile 编…...
git 的使用方法 (下 - 远程仓库和图形化)
目录前言:一、什么是协同开发二、Gitee 使用协同开发1. 首先注册一个码云账号2. 新建一个仓库3. 根据下图把新建仓库设置为开源4. 在远端合并分支的方法5. 链接 git 远程6. 提交(同步)远程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. 数组中重复的数字 题:在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数…...
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类型的硬盘为例,使用mount命令进行挂载5. 问题1:进程占用了磁盘6. 问题2:磁盘权限为只读的7. 永久挂…...
拖拽删除元素、拖拽排序、拖拽预览图片和拖拽移动元素
介绍 HTML5 提供了专门的拖拽与拖放的 API,目前各浏览器都已支持,包括 IE。HTML 拖放(Drag and Drop)接口使应用程序能够在浏览器中使用拖放功能。例如,用户可使用鼠标选择可拖拽(draggable)元素…...
yarn的global安装命令不生效
问题 yarn全局安装某个依赖完成之后,但依赖没有生效,一般有两种情况导致的。 解决思路 1.yarn命令问题 yarn在全局安装某个依赖时,global要紧接在yarn之后,然后才是add yarn global add xxxx如果出现global在add之后ÿ…...
如何发布自己的npm包?
1 文件组成 package.json文件components文件css样式文件index.js文件 2 package.json配置 description:描述title:题目keywords:搜索关键词typings:指定TypeScript的入口文件main:加载的入口文件module:…...
达梦数据库 闪回查询
当用户操作不慎导致错误的删改数据时,非常希望有一种简单快捷的方式可以恢复数据。闪回技术,就是为了用户可以迅速处理这种数据逻辑损坏的情况而产生的。 闪回技术主要是通过回滚段存储的 UNDO 记录来完成历史记录的还原。如果提交了,还没有…...
java基础学习 day44(多态的优点和劣势)
1. 多态的优势 在多态形式下,右边对象可以实现解耦合(即之后的代码与右边的子类对象不绑定,在更改子类对象后,之后的代码仍可以使用),便于扩展和维护在定义方法的时候,使用父类型作为参数&…...
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日美股盘前,零售巨无霸沃尔玛公布了截至1月的2023财年第四季度业绩报告。财报中不乏可圈可点之处,但是利润迎来六年首降,新财年的利润指引要也比预期低很多,可以说喜忧参半。 一、Q4业绩可圈可点 营收方面:在本…...
Python学习笔记丨while、for、if循环结构基础知识与易错点
Python流程控制 本篇笔记的主要内容是:条件控制和循环控制,包括if语句、while语句、for语句等。 Python条件控制 if (m : 1) > 0: # :是海象运算符,用于在函数内部为变量赋值 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实现写在前面,本系列笔记参考的是AutoLabor的教程,具…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...
