C语言杂记(指针篇)
指针篇
指针就是地址,地址就是指针 指针变量就是存放地址的变量
*号只有定义的时候表示定义指针变量,其他表示从地址里面取内容
通过指针的方法使main函数中的data1和data2发生数据交换。
#include <stdio.h>
void chang_data(int *data1,int *data2)
{int tmp;tmp = *data1;*data1 = *data2;*data2 = tmp;}int main()
{int data1 = 10;int data2 = 20;chang_data(&data1,&data2);printf("data1:%d data2:%d\n",data1,data2);return 0;
}
============================================================================
指针指向固定的区域
volatile :防止编译器进行编译优化,导致原来的值发生变化
#include <stdio.h>int main()
{volatile unsigned int *p = (volatile unsigned int *)0x0000000001234567;printf("p:%p\n",p);return 0;
}
============================================================================
输入三个数,要求不管怎么输入,在输出的时候要由大到小输出,用函数封装的方法
#include <stdio.h>
int func(int *data1,int *data2,int *data3)
{int tmp;if(*data1 < *data2){tmp = *data1;*data1 = *data2;*data2 = tmp;}if(*data1 < *data3){tmp = *data1;*data1 = *data3;*data3 = tmp;}if(*data2 < *data3){tmp = *data2;*data2 = *data3;*data3 = tmp;}}
int main()
{int data1;int data2;int data3;scanf("%d %d %d",&data1,&data2,&data3);func(&data1,&data2,&data3);printf("大到小:%d %d %d \n",data1,data2,data3);return 0;
}
============================================================================
1.定义一个指针变量指向数组
在C语言当中,数组名(不包括形参数组名)代表数组中首元素的地址,所以p = &a[0];//或者p =a;这两个等价的
2. 指针的偏移,偏移多少根据指针的类型,int偏移四个字节,char就偏移一个字节,使用的指针偏移遍历数组
3.指针的访问效率是远远大于数组下标的访问效率的
int main()
{int i = 0;int a[] = {1,2,3};int *p;p = &a[0];//或者p = a;for(i=0;i<sizeof(a)/sizeof(a[0]);i++){printf("a[%d] = %d \n",i,*p++);}p = a;//让指针重新指向数组的首元素地址return 0;
}
============================================================================
64位操作系统,一个指针占8个字节,所以八个字节表示一个地址
struct demo{int a;char c;
};
int main()
{struct demo *test;printf("sizeof int *:%d\n",sizeof(int *));printf("sizeof char *:%d\n",sizeof(char *));printf("sizeof double *:%d\n",sizeof(double *));printf("sizeof struct *:%d\n",sizeof(test));return 0;
}
============================================================================
- 函数封装数组初始化和遍历
- 作为形参的指针,在调用函数时也会分配自己的一个地址,作为指针,指向传过来的地址(下面传过来的main函数arr的首地址),后续就是对传过来的地址进行操作
ps:下面输出遍历的时候为什么不用把parr重新指向arr的首地址,因为这是两个函数,每个传过来的就是parr就是arr的首地址
#include <stdio.h>void Init_arr(int *parr,int len)
{int i= 0;for(i=0;i<len;i++){*parr = i;parr++; }
}void Printf_arr(int *parr,int len)
{int *tmp2;for(int i = 0;i<len;i++){printf("arr:%d\n",*parr);parr++;}}int main()
{int arr[5];int len = sizeof(arr)/sizeof(arr[0]);Init_arr(arr,len);Printf_arr(arr,len);return 0;
}
============================================================================
练习:数组翻转
#include <stdio.h>void Init_arr(int *parr,int len)
{int i= 0;for(i=0;i<len;i++){*parr = i;parr++; }
}void Overturn_arr(int *arr,int len)
{int i,j;int tmp;for(i=0;i<(len/2);i++){j = len-1-i;tmp = *(arr+i);*(arr+i) = *(arr+j);*(arr+j) = tmp;
}
}
void Printf_arr(int *parr,int len)
{for(int i = 0;i<len;i++){printf("arr:%d\n",*parr);parr++;}}int main()
{int arr[5];int len = sizeof(arr)/sizeof(arr[0]);Init_arr(arr,len);Overturn_arr(arr,len);Printf_arr(arr,len);return 0;
}
============================================================================
二维数组的认知 现在有一个二维数组,我们可以把二维数组理解为父子数组,还有数组名就是地址
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
那么父数组的名字就是a,而字数组的名字就是a[0],a[1],a[2],那么我们可以看出a的地址和a[0]的地址是一样的,但是要注意他们的偏移量是不一样的,a+1偏移的是一整个子数组的大小,a[0]+1是偏移一个数组元素的大小。
a[0] 等价于 &a[0][0] a[1]等价于 = &a[1][0] a[2]等价于 = &a[2][0]
那么a表示父数组的地址,a[0]表示的字数组的首地址
(a)等价与a[0]的首地址(因为a不可能取到整个子数组的值),*(a)+1就是(a[0])+1
#include <stdio.h>
int main()
{int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};printf("a父数组地址 IP:%p %d\n",a,*(a));printf("a[0]子数组地址 IP:%p %d\n",a[0],*(a[0]));printf("a+1父数组地址偏移 IP:%p %d\n",(a+1),*(a+1));printf("a[0]+1字数组地址偏移 IP:%p %d\n",(a[0]+1),*(a[0]+1));//*(a)等价与a[0]的首地址,*(a)+1就是(a[0])+1printf("*(a)字数组地址偏移 IP:%p *(a)+1的地址: %p\n",*(a),*(a)+1);return 0;
}
总结:
============================================================================
数组指针:就是数组的指针,其实就是一个指向数组的指针。 数组指针才是等同于二维数组名
#include <stdio.h>
int main()
{int arr[2][3] = {{1,2,3},{4,5,6}};int (*p)[3];//指向有3个元素数组的指针p = arr;int i,j;printf("p=%p\n",p);printf("++p:%p\n",++p);//这里看出地址偏移是12字节,就是一个子数组的大小p = arr;//这里让p重新指向二维数组名,再使用p遍历数组for(i=0;i<2;i++){for(j=0;j<3;j++){//printf("arr:%d\n",arr[i][j]);printf("arr:%d\n",*(*(p+i)+j));}}return 0;
}
============================================================================
数组指针的和二维数组的配合使用
题目:用数组指针方法,输出二维数组任意行列的数
#include <stdio.h>void InputNum(int *hang,int *lie)
{printf("输入行列号:\n");scanf("%d %d",hang,lie);
}int SearchNum(int (*p)[4],int hang,int lie)
{return (*(*(p+hang)+lie));
}int main()
{int a[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};int hang,lie;int data;//提示输出InputNum(&hang,&lie);//找到对于的数字data = SearchNum(a,hang,lie);//打印出来printf("第%d行第%d列的数字为:%d\n",hang,lie,data);return 0;
}
============================================================================
函数指针,就是一个指向函数入口地址的指针。
1.函数指针:如果程序中定义了一个函数,在编译的时候,编译系统会为函数代码分配一段存储空间,这段存储空间的起始地址(又成为入口地址)称为这个函数的指针。
2.函数名就是地址
3.如何定义一个函数指针变量:int (*p)(int a,int b)
4.定义函数指针的时候要和指向的函数的类型保持一致
#include <stdio.h>void printfWeclme()
{printf("hello world\n");}int DataAdd(int data)
{return ++data;}int main()
{void (*p)(); //函数指针的定义int (*p2)(int data);p = printfWeclme;//指向printfWeclme这个函数p2 = DataAdd;(*p)();//利用函数指针调用这个函数printf("++data:%d\n",(*p2)(10));return 0;
}
练习:用函数指针实现两个整数ab,输入1 2 或者3,1:输出ab中的大者,2:输出ab中的小者,3:输出ab之和
#include <stdio.h>
#include <stdlib.h>
int GetMax(int a,int b)
{int Max;if(a>b){Max = a;}else{Max = b;}return Max;
}int GetMin(int a,int b)
{int Min;if(a<b){Min = a;}else{Min = b;}return Min;
}float GetAvg(int a,int b)
{return ((float)a+(float)b)/2;
}int dataHandler(int a,int b,int (*func1)(int,int))
{int ret;ret = (*func1)(a,b);return ret;}float dataHandler2(int a,int b,float (*func2)(int,int))
{float ret;ret = (*func2)(a,b);return ret;}
int main()
{int a = 10;int b = 20;int mark;int ret;float ret2;int (*func1)(int,int);float (*func2)(int,int);printf("Input:");scanf("%d",&mark);switch(mark){case 1:func1 = GetMax;break;case 2:func1 = GetMin;break;case 3:func2 = GetAvg;break;default:printf("Input error\n");exit(-1);}if(mark != 3){ret = dataHandler(a,b,func1);printf("ret:%d\n",ret);}else{ret2 = dataHandler2(a,b,func2);printf("ret2:%0.2f\n",ret2);}return 0;
}
============================================================================
数组指针:
理解::指针数组就是存放指针的数组,数组的每一项都是指针变量
int main()
{int a = 1;int b = 2;int c = 3;int* arr[3] = {&a,&b,&c};for(int i=0;i<3;i++){printf("%d ",*(arr[i]));} return 0;
}
定义一个函数指针数组,然后进行函数调用:
#include <stdio.h>
#include <stdlib.h>int GetMax(int a,int b)
{int Max;if(a>b){Max = a;}else{Max = b;}printf("Max:%d\n",Max);return Max;
}int GetMin(int a,int b)
{int Min;if(a>b){Min = b;}else{Min = a;}printf("Min:%d\n",Min);return Min;
}int main()
{int a = 10;int b = 20;int (*pfun[2])(int,int) = {GetMax,GetMin};//定义了一个指向函数入口的函数指针数组,每一项都指向一个函数入口地址for(int i=0;i<2;i++){(*pfun[i])(a,b);//进行调用}return 0;
}
============================================================================
指针函数:返回指针值的函数
有3个学生,每个学生对于四门成绩,要求用用户输入学生序号后,输出该学生的全部成绩。用函数指针实现
#include <stdio.h>int *getPosPenson(int pos,int (*pstu)[4])//函数指针
{int *p;p = (int *)(pstu+pos);return p;}int main()
{int arr[3][4] = {{1,2,3,4},{5,6,7,8},{45,52,63,54} };int *ppos;int pos;//学生0 1 2do{printf("输入学生012:");scanf("%d",&pos);}while(pos!=0 && pos!=1 && pos!=2 );ppos = getPosPenson(pos,arr);for(int i=0;i<4;i++){printf("%d ",*(ppos++));}return 0;
}
============================================================================
二级指针:保存指针地址的指针
#include <stdio.h>int main()
{int data = 10;int *p;p = &data;int **p2;printf("data的地址:%p\n",&data);printf("p存放的地址(data的地址):%p\n",p);printf("p本身的地址:%p\n",&p);p2 = &p;printf("p2保存的地址(p本身的地址):%p\n",p2);printf("*p2是:%p\n",*p2);//这里取到的应该是data的地址printf("**p2是:%d\n",**p2);//这里就取到data的值了return 0;
}
============================================================================
下面对于ppos的理解
#include <stdio.h>void getPosPenson(int pos,int (*pstu)[4],int **ppos)//函数指针
{*ppos = (int *)(pstu+pos);//*ppos取到的就是main函数一级指针ppos的地址,这个指针指向了pstu这个指针的偏移地址,所以main函数中的ppos就再*(取一次内容)就访问到里面的值了}int main()
{int arr[3][4] = {{1,2,3,4},{5,6,7,8},{45,52,63,54} };int *ppos;int pos;//学生0 1 2do{printf("输入学生012:");scanf("%d",&pos);}while(pos!=0 && pos!=1 && pos!=2 );getPosPenson(pos,arr,&ppos);//这里传过去的时ppos的地址(指针的地址需要二级指针来承接)for(int i=0;i<4;i++){printf("%d ",*(ppos++));}return 0;
}
============================================================================
二级指针不能简单粗暴指向二维数组
============================================================================
搞懂下面这张图
================================================================================================================================================================
相关文章:
C语言杂记(指针篇)
指针篇 指针就是地址,地址就是指针 指针变量就是存放地址的变量 *号只有定义的时候表示定义指针变量,其他表示从地址里面取内容 通过指针的方法使main函数中的data1和data2发生数据交换。 #include <stdio.h> void chang_data(int *data1,int *da…...
ES window 系统环境下连接问题
环境问题:(我采用的版本是 elasticsearch-7.9.3)注意 开始修正之前的配置:前提:elasticsearch.yml增加或者修正一下配置:xpack.security.enabled: truexpack.license.self_generated.type: basicxpack.secu…...
hexo部署github搭建个人博客 完整详细带图版(更新中)
文章目录0. 前置内容1. hexo创建个人博客2. GitHub创建仓库3. hexo部署到GitHub4. 常用命令newcleangenerateserverdeploy5. 添加插件5.1 主题5.2 博客基本信息5.3 创建新的菜单5.4 添加搜索功能5.5 添加阅读时间字数提示5.6 打赏功能5.7 切换主题5.8 添加不蒜子统计5.9 添加百…...
SpringBoot集成DruidDataSource实现监控 SQL 性能
一、快速入门 1.1 基本概念 我们都使用过连接池,比如C3P0、DBCP、hikari、Druid,虽然 HikariCP 的速度稍快,但 Druid 能够提供强大的监控和扩展功能。Druid DataSource 是阿里巴巴开发的号称为监控而生的数据库连接池,它不仅可以…...
maven镜像源及代理配置
在公司使用网络一般需要设置代理, 我在idea中创建springboot工程时,发现依赖下载不了,原以为只要浏览器设置代理,其他的网络访问都会走代理,经过查资料设置了以下几个地方后工程创建正常,在此记录给大家参考…...
【Java面试篇】Spring中@Transactional注解事务失效的常见场景
文章目录Transactional注解的失效场景☁️前言🍀前置知识🍁场景一:Transactional应用在非 public 修饰的方法上🍁场景二: propagation 属性设置错误🍁场景三:rollbackFor属性设置错误dz…...
【C】分配内存的函数
#include <stdlib.h>//分配所需的内存空间,并返回一个指向它的指针。 void *malloc(size_t size);//分配所需的内存空间,并返回一个指向它的指针。并且calloc负责把这块内存空间用字节0填//充,而malloc并不负责把分配的内存空间清零 vo…...
IDEA 断点总是进入class文件没有进入源文件解决
前言 idea 断点总是进入class文件没有进入源文件解决 问题 在源文件里打了断点,断点模式启动时却进入了class文件里的断点,而没有进入到java源文件里的断点。 比如:我在 A.java 里打了断点,调试时却进入到了 jar 包里的 A.clas…...
【flink】 flink入门教程demo 初识flink
文章目录通俗解释什么是flink及其应用场景flink处理流程及核心APIflink代码快速入门flink重要概念什么是flink? 刚接触这个词的同学 可能会觉得比较难懂,网上搜教程 也是一套一套的官话, 如果大家熟悉stream流,那或许会比较好理解…...
LeetCode 1487. 保证文件名唯一
【LetMeFly】1487.保证文件名唯一 力扣题目链接:https://leetcode.cn/problems/making-file-names-unique/ 给你一个长度为 n 的字符串数组 names 。你将会在文件系统中创建 n 个文件夹:在第 i 分钟,新建名为 names[i] 的文件夹。 由于两个…...
详细剖析|袋鼠云数栈前端框架Antd 3.x 升级 4.x 的踩坑之路
袋鼠云数栈从2016年发布第⼀个版本开始,就始终坚持着以技术为核⼼、安全为底线、提效为⽬标、中台为战略的思想,坚定不移地⾛国产化信创路线,不断推进产品功能迭代、技术创新、服务细化和性能升级。 在数栈过去的产品迭代中受限于当前组件的…...
【C++PrimerPlus】第三章 处理数据
文章目录前言内容目录3.1 简单变量3.1.2 变量名3.1.2 整形3.1.3 整形short,int,long,long long3.1.4 无符号类型3.1.5 选择整形类型3.1.6 整形字面值3.1.7 C如何确定常量的类型3.1.8 char类型:字符和小整数3.1.9 bool类型3.2 const修饰符3.3浮点数3.3.1 书写浮点数3…...
【基础算法】单链表的OJ练习(1) # 反转链表 # 合并两个有序链表 #
文章目录前言反转链表合并两个有序链表写在最后前言 上一章讲解了单链表 -> 传送门 <- ,后面几章就对单链表进行一些简单的题目练习,目的是为了更好的理解单链表的实现以及加深对某些函数接口的熟练度。 本章带来了两个题目。一是反转链表&#x…...
离散数学笔记(1)命题逻辑
文章目录1.命题符号化及联结词基本概念本节题型2.命题公式及分类基本概念本节题型1.命题符号化及联结词 基本概念 命题的定义:能够判断真假的陈述句称为命题。 备注:感叹句、疑问句、祈使句和类似于xy>5之类真值不唯一的句子都不是命题。 真值的真假…...
IDEA Android 网格布局(GridLayout)示例(计算器界面布局)
网格布局(GridLayout) 示例程序效果(实现类似vivo手机自带计算器UI) 真机和模拟器运行效果: 简述: GridLayout(网格布局)和TableLayout(表格布局)有类似的地方,通俗来讲可以理解为…...
【蓝桥杯嵌入式】拓展板之数码管显示
文章目录硬件电路连接方式函数实现文章福利硬件电路 通过上述原理图,可知拓展板上的数码管是一个共阴数码管,也就是说某段数码管接上高电平时,就会点亮。 上述原理图还给出一个提示,即:三个数码管分别与三个74HC59…...
Web Spider案例 网洛克 第三题 AAEncode加密 练习(七)
声明 此次案例只为学习交流使用,抓包内容、敏感网址、数据接口均已做脱敏处理,切勿用于其他非法用途; 文章目录声明一、资源推荐二、逆向目标三、抓包分析 & 下断分析逆向3.1 抓包分析3.2 下断分析逆向拿到混淆JS代码3.3 AAEncode解决方…...
【javaScript面试题】2023前端最新版javaScript模块,高频24问
🥳博 主:初映CY的前说(前端领域) 🌞个人信条:想要变成得到,中间还有做到! 🤘本文核心:博主收集的关于javaScript的面试题 目录 一、2023javaScript面试题精选 1.js的数据类型…...
Hadoop集群启动从节点没有DataNode
一、问题背景 之前启动hadoop集群的时候都没有问题,今天启动hadoop集群的时候,从节点的DataNode没有启动起来。 二、解决思路 遇见节点起不来的情况,可以去看看当前节点的日志文件 我进入当前从节点的hadoop安装目录的Logs文件下去查看日…...
FIFO IP Core
FIFO IP Core 先进先出的缓存器常常被用于数据的缓存,或者高速异步数据交互(跨时钟信号传递)和RAM和ROM的区别是没有地址线,无法指定地址 写时钟(Write Clock Domain),读时钟写复位(wr_rst),读…...
从FPGA说起的深度学习(四)
这是新的系列教程,在本教程中,我们将介绍使用 FPGA 实现深度学习的技术,深度学习是近年来人工智能领域的热门话题。在本教程中,旨在加深对深度学习和 FPGA 的理解。用 C/C 编写深度学习推理代码高级综合 (HLS) 将 C/C 代码转换为硬…...
pytorch入门7--自动求导和神经网络
深度学习网上自学学了10多天了,看了很多大神的课总是很快被劝退。终于,遇到了一位对小白友好的刘二大人,先附上链接,需要者自取:https://b23.tv/RHlDxbc。 下面是课程笔记。 一、自动求导 举例说明自动求导。 torch中的…...
QT 之wayland 事件处理分析基于qt5wayland5.14.2
1. Qt wayland 初始化 接收鼠标/案件,触摸屏等事件事件 QWaylandNativeInterface : public QPlatformNativeInterface 在QWaylandNativeInterface 继承qpa 接口类QPlatformNativeInterface; 1.1 初始化鼠标: void *QWaylandNativeInterface::nativeR…...
【this 和 super 的区别】
在 Java 中,this 和 super 都是关键字,表示当前对象和父类对象。 this 关键字可以用于以下几种情况: 引用当前对象的成员变量,方法和构造方法,用于区分局部变量和成员变量重名的情况; 调用当前类的另外一…...
K8s:Monokle Desktop 一个集Yaml资源编写、项目管理、集群管理的 K8s IDE
写在前面 Monokle Desktop 是 kubeshop 推出的一个开源的 K8s IDE相关项目还有 Monokle CLI 和 Monokle Cloud相比其他的工具,Monokle Desktop 功能较全面,涉及 k8s 管理的整个生命周期博文内容:Monokle Desktop 下载安装,项目管理…...
自动化测试实战篇(8),jmeter并发测试登录接口,模拟从100到1000个用户同时登录测试服务器压力
首先进行使用jmeter进行并发测试之前就需要搞清楚线程和进程的区别还需要理解什么是并发、高并发、并行。还需要理解高并发中的以及老生常谈的,TCP三次握手协议和TCP四次握手协议**TCP三次握手协议指:****TCP四次挥手协议:**进入Jmeter&#…...
ATTCK v12版本战术实战研究—持久化(二)
一、前言前几期文章中,我们介绍了ATT&CK中侦察、资源开发、初始访问、执行战术、持久化战术的知识。那么从前文中介绍的相关持久化子技术来开展测试,进行更深一步的分析。本文主要内容是介绍攻击者在运用持久化子技术时,在相关的资产服务…...
python函数式编程
1 callable内建函数判断一个名字是否为一个可调用函数 >>> import math >>> x 1 >>> y math.sqrt >>> callable(x) False >>> callable(y) True 2 记录函数(文档字符串) >>> def square(x): …...
3.linux下安装mysql
1.安装前的环境准备 查看是否安装过mysql 首先检测Linux操作系统中是否安装了MySQL: # rpm -qa | grep -i mysql 卸载安装包 如果有信息出现,则进行删除,命令如下: # rpm -e --nodeps 包名 删除老版本mysql的开发头文件和…...
17、MySQL分库分表,原理实战
MySQL分库分表,原理实战 1.MyCAT分布式架构入门及双主架构1.1 主从架构1.2 MyCAT安装1.3 启动和连接1.4 配置文件介绍2.MyCAT读写分离架构2.1 架构说明2.2 创建用户2.3 schema.xml2.4 连接说明2.5 读写测试2.6 当前是单节点3.MyCAT高可用读写分离架构3.1 架构说明3.3 schema.xm…...
网站统计代码添加/专业seo培训学校
[oracle] to_date() 与 to_char() 日期和字符串转换 to_date("要转换的字符串","转换的格式") 两个参数的格式必须匹配,否则会报错。 即按照第二个参数的格式解释第一个参数。 to_char(日期,"转换格式" ) 即把给定的日期按照“转换…...
为什么做网站还要续费/百度网址ip
为什么80%的码农都做不了架构师?>>> 序 本文主要研究下springboot2的ScheduledTasksEndpoint 实例 注解形式 Component public class ScheduleTask {Scheduled(cron "0 0 5 * * ?")public void cronJob(){}Scheduled(fixedDelay 2*60*1000…...
漯河小学网站建设/湖南靠谱的关键词优化
目录 概述测试环境 安装过程配置启动客户端介绍多级DC的ldif文件的配置 [一]、概述 什么叫LDAP呢,概念的东西这里就不多讲了,网上搜索下有很多,本文的重点是介绍如何在windows平台上安装和配置openLDAP软件。 openLDAP官方网站࿱…...
蒙阴做网站/如何创建一个个人网站
通信改变未来,从古至今信息的传输和获取从来就没有缺少过,之所以谁能取得胜利就是谁掌握的资源多,其中信息资源尤为重要,只要获取到更多的信息你就能提前做出应对策略。因此未来一定是信息的未来,作为信息传输的技术和…...
网站设计制作全网优惠/免费顶级域名申请网站
通过对TCP/IP协议的学习,本人写了一个可以实现对PCAP文件中的IPV4下的TCP流提取,以及提取指定的TCP流,鉴于为了学习,没有采用第三方包解析pcap,而是对bytes流进行解析,其核心思想为:若想要提取T…...
网站建设优化现状图表/小说推广平台有哪些
题意简概: 输入n个元素组成的序列S,你需要找一个乘积最大的连续子序列。如果这个最大的乘积不是正数,应输出0,表示无解。1<n<18,-10<Si<10。 Sample Input32 4 -352 5 -1 2 -1Sample OutputCase #1: The m…...