C语言---------深入理解指针
目录
一、字符指针
二、指针数组:
三、数组指针:
1、定义:
2、&数组名和数组名区别:
3、数组指针的使用:
四、数组参数,指针参数:
1、一维数组传参:
2、二维数组传参:
3、一级指针传参:
4、二级指针传参:
五、函数指针:
1、定义:
2、函数名和&函数名:
3、函数指针的调用:
六、函数指针数组:
七、指向函数指针数组的指针
一、字符指针
定义:字符指针就是指向一个字符串的指针。指针类型为char*
int main()
{char c = 'z';char* pc = &c;printf("%c\n", c);return 0;
}
或者:
int main()
{const char* pc = "abcdef";printf("%s\n", pc);return 0;
}
这里因为是个常量字符串,所以可以用const修饰来达到后面不会被修改的问题。
上面const char* pc = "abcdef"这里并不是将abcdef赋给pc的指针变量里面,而是将字符串的首字符的地址放在pc中。
接下来看一个经典题目:
#include <stdio.h>
int main()
{char str1[] = "hello ppr.";char str2[] = "hello ppr.";char *str3 = "hello ppr.";char *str4 = "hello ppr.";if(str1 ==str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if(str3 ==str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");return 0;
}
这串代码的意思是:
将hello ppr.给到数组str1和str2中,判断二者是否相等。
将hello ppr.的地址给到str3和str4中,判断二者是否相等。
那么为什么会出现这样的结果呢?
对于str1和str2,这两个是开辟了两块不同的空间,比较数组名就是比较首元素的地址,毕竟空间不同肯定比较出来就会不同。
对于str3和str4
首先要知道这是一个常量字符串是不能够被修改的,所以在内存就没有必要存储两份了,那么这两个字符指针就都会指向那同一块空间。
二、指针数组:
定义:存放指针的数组就是指针数组。
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 arr4[5] = { 0,0,0,0,0 };int* arr[4] = {arr1,arr2,arr3,arr4};for (int i = 0; i < 4; i++){for (int j = 0; j < 5; j++){//printf("%d ", arr[i][j]);printf("%d ", *(*(arr + i) + j));}printf("\n");}return 0;
}
如上代码所示:
arr先和右边的[]结合,就是一个数组,然后里面每一个元素都是int* ,这就是一个存放整形指针的数组。
例如:
int* arr1[10]//这是一个整形指针的数组,里面有10个元素。
char* arr2[10]//这是一个这是一个字符指针的数组,里面有10个元素。
char** arr3[10]这是一个二级字符指针的数组,里面有10个元素。
三、数组指针:
1、定义:
定义:这是一个指针,是能够指向数组的指针。
写法:int* p1[10] or int (*p2)[10]
这两种写法是哪一种呢?
很显然是后面的,因为前一个和指针数组一样。
因为p2和[]结合的优先级高于*,所以需要用小括号来改变其结合的优先顺序。
2、&数组名和数组名区别:
例如:
对于int arr[10];
arr和&arr分别有啥区别?
同样从代码入手:
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };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和&arr的话,二者是相等的,但是如果对二者都进行指针运算+1后,arr跳过了增加了4,跳过了一个整型,而&arr增加了28(十六进制),换算成十进制为40,所以就是跳过了10个整型,也就是这个数组。
故有结论:arr是这个数组的首元素的地址
&arr是这整个数组的地址,所以+1是跳过这个数组的大小
3、数组指针的使用:
数组指针大多时候是在二维数组的传参中使用的,在一维数组中的作用不大。
依然从代码入手:
void print_arr1(int arr[3][5], int row, int col)
{int i = 0;for (i = 0; i < row; i++){for (int j = 0; j < col; j++){printf("%d ", arr[i][j]);}printf("\n");}
}
void print_arr2(int(*arr)[5], int row, int col)
{int i = 0;for (i = 0; i < row; i++){for (int j = 0; j < col; j++){printf("%d ", arr[i][j]);}printf("\n");}
}
int main()
{int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };print_arr1(arr, 3, 5);printf("\n");//数组名arr,表示首元素的地址//但是二维数组的首元素是二维数组的第一行//所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址//可以数组指针来接收print_arr2(arr, 3, 5);return 0;
}
如上代码所示:
这里用了自己创建的两个打印二维数组的函数,在其中唯一不同的是形参的接收不同,在print_arr1中,用传统的二维数组来接收,而在print_arr2中,用数组指针(指向数组的指针)来接收是一样的效果。
拓展:int (*parr[10])[5] 这是个啥?
首先parr和[10]结合成为一个数组,所以parr是个数组,在这个数组里面有10个元素,
其中每个元素的类型是int(*)[5]这个数组指针
四、数组参数,指针参数:
1、一维数组传参:
#include <stdio.h>
void test(int arr[])
{}
void test(int arr[10])
{}
void test(int* arr)
{}
void test2(int* arr[20])
{}
void test2(int** arr)
{}
int main()
{int arr[10] = { 0 };int* arr2[20] = { 0 };test(arr);test2(arr2);
}
如上代码中,所有传参均是可以的,用数组接收或者用指针接收。
2、二维数组传参:
3、一级指针传参:
当一个函数的参数部分为一个一级指针的时候,函数能接收的参数有:
void test(int* a)
{}int main()
{int a = 10;int* pa = &a;int arr[10];test(&a);test(pa);test(arr);return 0;
}
4、二级指针传参:
当一个函数的参数部分为一个二级指针的时候,函数能接收的参数有:
void test(int** a)
{}int main()
{int** a ;int* pa ;int* arr[10];test(a);test(&pa);test(arr);return 0;}
五、函数指针:
1、定义:
类比一下:
数组指针是指向数组的指针,函数指针就是指向函数的指针。
(类比于数组指针)
那么函数指针该怎么写呢?
例如有一个函数int Add(int x,int y);
假设我要定义一个函数指针变量名为ppr只想Add函数
那么首先要是一个指针就需要用()来进行:(*ppr)
然后需要是个函数里面写形参的类型就是:(*ppr)(int,int)
最后看返回值:int (* ppr)(int,int)= &Add;
2、函数名和&函数名:
函数名和&函数名在C语言中大多数情况下都是等效的,都表示函数的地址。然而,使用&可以使代码更加清晰明确。
3、函数指针的调用:
int Add(int x, int y)
{return x + y;
}int main()
{//int (*pf)(int, int) = &Add;int (* pf)(int, int) = Add;//int ret = Add(2, 3);int ret = pf(2, 3);int ret = (*pf)(2, 3);printf("%d\n", ret);return 0;
}
如上代码所示:
将Add赋给pf后pf就可以像Add函数一样地调用了,也可以对pf解引用后调用,语法上可以这样理解。
六、函数指针数组:
存放函数指针的数组就是函数指针数组。
写法:
在函数指针的基础上改变:
如上所示:
int (* ppr)(int,int)这是一个函数指针,
int (* ppr[5])(int,int)此时ppr会和[5]先结合,就是一个数组,去掉数组名和个数剩下的
int (*)(int,int)这个就是函数指针类型。
应用场景:转移表
七、指向函数指针数组的指针
我们从函数指针数组入手:
int (* pr[5])(int,int)这是一个函数指针,
现在我想要一个指向函数指针数组的指针,所以就可以将ppr与一个*结合使其成为指针
int (* (*ppr)[5])(int,int) = ≺
这个就成为了 指向函数指针数组的指针
这个的函数指针类型就是去掉 (*ppr)
这个int (* [5] )(int,int)就是一个函数指针类型
接下来画个图来理解:
相关文章:
C语言---------深入理解指针
目录 一、字符指针 二、指针数组: 三、数组指针: 1、定义: 2、&数组名和数组名区别: 3、数组指针的使用: 四、数组参数,指针参数: 1、一维数组传参: 2、二维数组传参&am…...
C++ 算法教程
归并排序 #include<iostream> using namespace std; template <class T> void Merge(T data[],int start,int mid,int end) {int len1 mid - start 1, len2 end - mid;int i, j, k;T* left new int[len1];T* right new int[len2];for (i 0; i < len1; i)…...
【支持向量机】问题梳理
学完支持向量机后我有些地方不太清楚,故做如下梳理: 1.为什么支持向量机模型认为一个点划分正确的标志是y(wxb)>1呢,为什么不是y(wxb)>0,比如y为1,wxb为0.5,大于0,则预测正确。 2.所以意思…...
车载网络安全指南 网络安全框架(二)
返回总目录->返回总目录<- 目录 一、概述 二、网络安全组织管理 三、网络安全活动 四、支撑保障 一、概述 汽车电子系统网络安全活动框架包含汽车电子系统网络安全活动、组织管理以及支持保障。其中,网络安全管理活动是框架的核心,主要指汽车电子系统生命周期各阶段…...
元数据、数据元、数据字典、数据模型及元模型的区别详解
在数据管理和分析领域,有许多相似的概念,如元数据、数据元、数据字典、数据模型和元模型。这些概念的定义和应用往往容易混淆。 数据元 数据元是通过一系列属性描述的数据单元,包括定义、标识、表示以及允许值等。这些属性帮助我们理解和使用…...
【百度智能体】零代码创建职场高情商话术助手智能体
一、前言 作为一个程序猿,工科男思维,走上职场后,总会觉得自己不会处理人际关系,容易背锅说错话,这时候如果有个助手能够时时刻刻提醒自己该如何说话如何做事情就好了。 而我们现在可以通过百度文心智能体平台构建各…...
实战项目: 负载均衡
0. 前言 这个项目使用了前后端,实现一个丐版的LeetCode刷题网站,并根据每台主机的实际情况,选择对应的主机,负载均衡的调度 0.1 所用技术与开发环境 所用技术: C STL 标准库 Boost 准标准库 ( 字符串切割 ) cpp- httplib 第三方开源网络库 ctemplate 第三方开源前端网…...
运维监控系统
做监控系统集成,持续更新ing 1.Prometheus k8s安装prometheusdocker部署prometheusthanos实现prometheus高可用部署 2.Grafana docker安装grafanagrafana的admin密码忘记了grafana使用mysql远程存储 3.Alertmanager 4.Consul 5.夜莺系统 6.时序数据库 6.1 …...
第3章 Unity 3D着色器系统
3.1 从一个外观着色器程序谈起 新建名为basic_diffuse.shader的文件,被一个名为basic_diffuse.mat的材质文件所引用,而basic_diffuse.mat文件则被场景中名为Sphere的game object的MeshRenderer组件所使用。 basic_diffuse.shader代码文件的内容如下所示…...
Qt项目天气预报(1) - ui界面搭建
ui中部 效果演示 ui效果 显示效果 控件列表 配合右图查看 居中对齐-label 设置label居中对齐(别傻傻的空格对齐了) 间距配置 widget03 外围的widget对象: 包含label 和 widget0301,如下图 widget0301 内围的widget对象,如下图 样式表 widget03 …...
一、从C语言到C++(一)
一、从C语言到C(一) C介绍C语言和C的联系C介绍 头文件命名空间定义命名空间使用命名空间中的名称使用using声明或指令命名空间与C语言的对比给命名空间起别名注意事项std 标准输入输出std::endl使用std::cout进行输出使用std::cin进行输入格式化输出 C介…...
MySQL(5)
聚合函数 GROUP BY 的使用 需求:查询各个部门的平均工资,最高工资SELECT department_id,AVG(salary),SUM(salary)FROM employeesGROUP BY department_id;需求:查询各个job_id的平均工资SELECT job_id,AVG(salary)FROM employeesGROUP BY jo…...
区块链之快照
定义 区块链快照是区块链技术中一个非常重要的概念,它可以帮助区块链系统提高性能和数据管理效率。 什么是区块链快照 区块链快照是指在某个时间点对整个区块链的状态进行保存和备份的过程。 快照会记录区块链上所有账户的余额、合约状态等信息,并将其序列化存储起来。 这样…...
自学前端第一天
HTML标签 ’HTML‘全程是‘hypertext Markup langage(超文本标记语言) HTML通过一系列的’标签(也称为元素)‘来定义文本、图像、链接。HTML标签是由尖括号包围的关键字。 标签通常成对存在,包括开始标签和结束标签(也称为双标签…...
SQL Server几种琐
SQL Server 中的锁类型主要包括以下几种,它们用于控制并发访问和数据一致性: 1. 共享锁(Shared Lock,S 锁): - 用于读取操作(如 SELECT 语句)。 - 允许多个事务同时读取同一资…...
redis 一些笔记1
redis 一、redis事务二、管道2.1 事务与管道的区别 三、主从复制3.13.2 权限细节3.3 基本操作命令3.4 常用3.4.1 一主几从3.4.2 薪火相传3.4.3 反客为主 3.5 步骤3.6 缺点 一、redis事务 放在一个队列里,依次执行,并不保证一致性。与mysql事务不同。 命…...
【计网复习】应用层总结(不含HTTP和错题重点解析)
应用层总结(不含HTTP和错题重点解析) 应用层简介 应用层的主要功能常见的应用层协议小林对于应用层通常的解释 网络应用模型 客户端-服务器模型(Client-Server Model, C/S) 特点优点缺点应用场景 对等网络模型(Peer-to…...
carbondata连接数优化
一,背景 carbondata的入库采用arbonData Thrift Server方式提供,由于存在异常的入库segments但是显示状态是success,所以每天运行另一个博客中的脚本,出现连接超时,运行不正常,排查是每天连接数太多&#x…...
云和运维(SRE)的半生缘-深读实证02
这个标题不算太夸张,云计算和很多IT岗位都有缘,但是和运维(SRE)岗位的缘分最深。 “深读实证”系列文章都会结合一些外部事件,点明分析《云计算行业进阶指南》书中的内容。本次分享介绍了下列内容: 我以运维…...
java基础操作5——java自定义获取任意年、月、日的起始和结束时间
在实际项目开发过程中,获取任意时间的起始和结束时间是常用操作,尤其对于统计业务来说,更是必要操作,理解了时间自定义的规律,对于开发人员的效率提升是大有裨益的。 一.获取任意年的起始和结束时间 1.获取任意年的起…...
【Java04】引用变量数组初始化的内存机制
引用类型数组指向的元素也是引用。其本质是: 由一个在栈上的引用数组变量指向一块堆内存;这块堆内存里存储的元素是引用,又分别指向其他堆内存。 class Person // Person是一个自定义的类 {public int age;puiblic double height;public vo…...
基于JSP的足球赛会管理系统
你好呀,我是计算机学长猫哥!如果有相关需求,文末可以找到我的联系方式。 开发语言:Java 数据库:MySQL 技术:JSP技术 工具:IDEA/Eclipse、Navicat、Maven 系统展示 首页 个人中心 球队介绍…...
博客摘录「 AXI三种接口及DMA DDR XDMA介绍(应用于vivado中的ip调用)」2024年6月10日
关键要点: 1.AXI Stream经过协议转换可使用AXI_FULL(PS与PL间的接口,如GP、HP和ACP)。 2.传输数据类里就涉及一个握手协议,即在主从双方数据通信前,有一个握手的过程。基本内容:数据的传输源会…...
Bigtable: A Distributed Storage System for Structured Data
2003年USENIX,出自谷歌,开启分布式大数据时代的三篇论文之一,底层依赖 GFS 存储,上层供 MapReduce 查询使用 Abstract 是一种分布式结构化数据存储管理系统,存储量级是PB级别。存储的数据类型和延时要求差异都很大。…...
RAG下的prompt编写探索
针对特定领域的回答,编写抽象的prompt需要在细节和灵活性之间找到平衡。我们需要一个既能涵盖普遍步骤又能适应不同问题的框架。以下是如何在这种情况下编写抽象prompt的方法,以及适用于各种技术领域的通用策略。 一、编写抽象Prompt的通用策略 定义用户问题和背景信息: 明…...
【计算机组成原理】指令系统考研真题详解之拓展操作码!
计算机组成原理:指令系统概述与深入解析 1. 指令系统概述 计算机软硬件界面的概念 在计算机组成原理中,指令系统扮演着至关重要的角色,它是计算机软硬件界面的核心。软件通过指令与硬件进行通信,硬件根据指令执行相应的操作。指…...
北航第六次数据结构与程序设计作业(查找与排序)选填题
一、 顺序查找的平均查找长度ASL(1 2 …… n)/ n (n 1)/ 2 二、 这半查找法的平均查找次数和判定树的深度有关系。若查找一个不存在的元素,说明进行了深度次比较。 注意,判定树不是满二叉树,因此深…...
Optional详解和常用API
目录 一、Optional简介 二、构建Optional对象三种方式 2.1 Optional.of(value) 2.1.1 使用案例 2.2 Optional.ofNullable(value) 2.2.1 使用案例 2.3 Optional.empty() 2.3.1 使用案例 三、Optional常用的api解析和使用案例 3.1 isPresent 3.1.1 使用案例 3.2 ifPrese…...
Unity 3D 物体的Inspector面板
1、Transform:位置、旋转、大小 2、Mesh Filter:物体的形状 3、Mesh Renderer:物体渲染(物体的衣服) 4、Collider:碰撞体...
闪烁与常亮的符号状态判断机制(状态机算法)
背景说明 在视觉项目中,经常要判断目标的状态,例如:符号的不同频率闪烁、常亮等。然而常规的视觉算法例如YOLO,仅仅只能获取当前帧是否存在该符号,而无法对于符号状态进行判断,然而重新写一个基于时序的卷积…...
建设银行 网站设置密码/合肥seo报价
1. 水平居中设置-行内元素 我们在实际工作中常会遇到需要设置水平居中的场景,比如为了美观,文章的标题一般都是水平居中显示的。 这里我们又得分两种情况:行内元素还是 块状元素,块状元素里面又分为定宽块状元素,以及…...
做网站电信运营许可证/营销推广方案ppt案例
zabbix官方的一句话描述zabbix: 监视任何事情适用于任何IT基础架构,服务,应用程序和资源的解决方案 Monitor anythingSolutions for any kind of IT infrastructure, services, applications, resources ---------------------------------…...
青岛新闻网/seo的基本工作内容
这一篇介绍了一下RHEL DHCP服务器配置,从DHCP服务器软件的安装开始。 [rootbys dhcp]# rpm -e dhcp #卸载DHCP相关的软件 提示无法卸载。是与另一文件关联 error: Failed dependencies: dhcp 12:3.0.5-23.el5 is needed by (installed) dhcp-…...
滁州做网站优化/百度投放广告收费标准
在本文中,我们会研究一些用于数据科学任务的 Python 库,而不是常见的比如 panda、scikit-learn 和 matplotlib 等的库。尽管像 panda 和 scikit-learn 这样的库,是在机器学习任务中经常出现的,但是了解这个领域中的其它 Python 产…...
个人备案网站做商业/营销策略都有哪些
最近在工作中遇到一个非常奇怪的问题,在两台主主同步的mysql数据库中,经常出现修改表结构后,两个库中结构不一致的情况,查看同步状态,木有任何报错,数据可正常同步,我自己在操作数据库进行索引创…...
专门做网站的公司 南阳/google安卓手机下载
目前互联网上有无数个开源的建站程序可供大家选择使用,对现在的站长来说真的是容易多了,10年前我作网站的时候,一个小聊天程序也要自己一句一句的写,看看现在的开源程序,层出不穷。太多了也就不知道选哪个好了…...