【C语言进阶】指针的高级应用(下)

文章目录

  • 一、指针数组与数组指针
    • 1.1 指针数组与数组指针的表达式
  • 二、函数指针
    • 2.1 函数指针的书写方式
  • 三、二重指针与一重指针
    • 3.1 二重指针的本质
    • 3.2 二重指针的用法
    • 3.3 二重指针与数组指针
  • 总结

在这里插入图片描述

一、指针数组与数组指针

(1)指针数组的实质是一个数组,这个数组中存储的内容全部是指针变量。
(2)数组指针的实质是一个指针,这个指针指向的是一个数组。

1.1 指针数组与数组指针的表达式

int *p[5]; int (*p)[5];	int *(p[5]);

一般规律:int *p;(p是一个指针); int p[5];(p是一个数组)

第一个:int *p[5];

核心是p,由于[]的优先级高于*,因此p先跟[]结合,p是一个数组,数组中的元素都是指针类型,指针指向的元素类型是int类型的;因此整个符号是一个指针数组。

第二个,int (*p)[5];

当存在()时候,作用是强制将()内的元素进行强制结合,无视优先级。因此先看()内的运算,()内核心是p,离他最近的是*,因此p是一个指针。*p再跟[]结合,说明指针p指向一个数组,数组有5个元素,数组中存的元素都是int类型;总结一下整个符号的意义就是数组指针。

第三个,int *(p[5]); 

解析方法和结论和第一个相同,()在这里是可有可无的,因为它可以无视优先级,强制将p和[]进行结合,因此p是数组。

注意:符号的优先级到底有什么用?其实是决定当2个符号一起作用的时候决定哪个符号先运算,哪个符号后运算。
当存在()时候,作用是强制将()内的元素进行强制结合,无视优先级。
遇到优先级问题怎么办?
第一,查优先级表;
第二,自己记住(只要记住[] . ->这几个优先级比较即可)。

二、函数指针

函数指针的实质(还是指针变量)
(1)函数指针的实质还是指针,还是指针变量。本身占4字节(在32位系统中,所有的指针都是4字节)
(2)函数指针、数组指针、普通指针之间并没有本质区别,区别在于指针指向的东西是个什么玩意。
(3)函数的实质是一段代码,这一段代码在内存中是连续分布的(一个函数的大括号括起来的所有语句将来编译出来生成的可执行程序是连续的),所以对于函数来说很关键的就是函数中的第一句代码的地址,这个地址就是所谓的函数地址,在C语言中用函数名这个符号来表示。
(4)结合函数的实质,函数指针其实就是一个普通变量,这个普通变量的类型是函数指针变量类型,它的值就是某个函数的地址(也就是它的函数名这个符号在编译器中对应的值)
在这里插入图片描述

2.1 函数指针的书写方式

(1)C语言本身是强类型语言(强类型语言的定义:每一个变量都有自己的变量类型),编译器担心我们定义的类型不匹配,因此要帮我们做严格的类型检查。这里要注意区分python这类的脚本语言、makefile,属于弱类型语言,对变量是没有类型定义的。
(2)所有的指针变量类型其实本质都是一样的,但是为什么在C语言中要去区分它们,写法不一样呢(譬如int类型指针就写作int *p; 数组指针就写作

int (*p)[5],函数指针就得写得更复杂)
int *p;
int a[5];
p=a;类型匹配,所以编译器不会警告也不会报错
p=&a;类型不匹配,p是int *类型,而&a是int (*)[5]类型。
int (*p1)[5];
p1=&a;类型匹配,都是int (*)[5]类型
假设有个函数是:void func(void); 
对应的函数指针:void (*p)(void); 
类型是:void (*)(void);通过指针来调用函数。

在这里插入图片描述
函数名称作为右值表示一坨代码的首地址,因此pFunc和func1(函数名)的类型是匹配的,都是void *(void)。pFunc就指向了函数func1。

(4)函数名和数组名最大的区别就是:函数名做右值时加不加&效果和意义都是一样的;但是数组名做右值时加不加&意义就不一样。这是编译器自己定义的。
(5)写一个复杂的函数指针的实例:譬如函数是strcpy函数(char *strcpy(char *dest, const char *src);),对应的函数指针是:char *(*pFunc)(char *dest, const char *src);
在这里插入图片描述
strcpy就是将复制功能,结果是:a=abc

三、二重指针与一重指针

(1)二重指针和一重指针本质都是指针变量,指针变量的本质就是变量。
(2)一重指针变量和二重指针变量本身都占4字节内存空间(32位平台)。

3.1 二重指针的本质

(1)二重指针和普通指针的差别就是它指向的变量类型必须是个一重指针。二重指针其实也是一种数据类型,编译器在编译时会根据二重指针的数据类型来做静态类型检查,一旦发现运算时数据类型不匹配编译器就会报错。
Char**类型就是指针指向的变量是char *类型。
Char *类型指针指向的变量是char类型。
Char **p:二重指针
char *p:一重指针
(2)C语言中如果没有二重指针行不行?其实是可以的。一重指针完全可以做二重指针做的事情,之所以要发明二重指针(函数指针、数组指针),就是为了让编译器了解这个指针被定义时定义它的程序员希望这个指针被用来指向什么东西(定义指针时用数据类型来标记,譬如int *p,就表示p要指向int型数据),编译器知道指针类型之后可以帮我们做静态类型检查。编译器的这种静态类型检查可以辅助程序员发现一些隐含性的编程错误,这是C语言给程序员提供的一种编译时的查错机制。
(3)为什么C语言需要发明二重指针?原因和发明函数指针、数组指针、结构体指针等一样的。

3.2 二重指针的用法

(1)二重指针指向一重指针的地址。
(2)二重指针指向指针数组的。
(3)实践编程中二重指针用的比较少,大部分时候就是和指针数组纠结起来用的。
(4)实践编程中有时在函数传参时为了通过函数内部改变外部的一个指针变量,会传这个指针变量的地址(也就是二重指针)进去。
在这里插入图片描述

3.3 二重指针与数组指针

(1)二重指针、数组指针、结构体指针、一重指针、普通变量的本质都是相同的,都是变量。
(2)所有的指针变量本质都是相同的,都是4个字节,都是用来指向别的东西的,不同类型的指针变量只是可以指向的(编译器允许你指向的)变量类型不同。
(3)二重指针就是指针数组指针

总结

(1)定义一个符号的关键在于:首先要搞清楚你定义的符号是谁(第一步:找核心);上面三个例子的核心都是p。其次,再来看谁跟核心最近、谁跟核心结合(第二步:找结合);之后继续向外扩展(第三步:继续向外结合直到整个符号完)。如果核心和*结合,表示核心是指针;如果核心和[]结合,表示核心是数组;如果核心和()结合,表示核心是函数。跟谁最近就是跟谁结合,但是如果核心左右两边都有符号怎么办?这个时候考虑优先级的问题,谁的优先级高就是跟谁先结合。
总结1:优先级和结合性是分析符号意义的关键
在分析C语言问题时不要胡乱去猜测规律,不要总觉得c语言无从捉摸,从已知的规律出发按照既定的规则去做即可。
总结2:学会逐层剥离的分析方法
找到核心后从内到外逐层的进行结合,结合之后可以把已经结合的部分当成一个整体,再去和整体外面的继续进行结合。
总结3:基础理论和原则是关键,没有无缘无故的规则

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/25131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux进程(二)

文章目录 进程(二)Linux的进程状态R (running)运行态S (sleeping)阻塞状态D (disk sleep)深度睡眠T(stopped)状态X(dead)状态Z&#x…

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--搭建Vue 前端工程[一]

文章目录 SSM--搭建Vue 前端工程--项目基础界面实现功能01-搭建Vue 前端工程需求分析/图解代码实现搭建Vue 前端工程下载node.js LTS 并安装: node.js 的npm创建Vue 项目使用idea 打开ssm_vue 项目, 并配置项目启动 Vue3 项目目录结构梳理Vue3 项目结构介绍 配置Vue 服务端口El…

Dockerfile构建mysql

使用dockerfile构建mysql详细教学加案例 Dockerfile 文件 # 使用官方5.6版本,latest为默认版本 FROM mysql:5.6 #复制my.cof至容器内 ADD my.cnf /etc/mysql/my.cof #设置环境变量 密码 ENV MYSQL_ROOT_PASSWORD123456my.cof 文件 [mysqld] character-set-server…

IDEA SpringBoot Maven profiles 配置

IDEA SpringBoot Maven profiles 配置 IDEA版本: IntelliJ IDEA 2022.2.3 注意:切换环境之后务必点击一下刷新,推荐点击耗时更短。 application.yaml spring:profiles:active: env多环境文件名: application-dev.yaml、 applicat…

【MATLAB第63期】基于MATLAB的改进敏感性分析方法IPCC,拥挤距离与皮尔逊系数法结合实现回归与分类预测

【MATLAB第63期】基于MATLAB的改进敏感性分析方法IPCC,拥挤距离与皮尔逊系数法结合实现回归与分类预测 思路 考虑拥挤距离指标与PCC皮尔逊相关系数法相结合,对回归或分类数据进行降维,通过SVM支持向量机交叉验证得到平均指标,来…

基于CentOS 7构建LVS-DR集群

DIPVIPRIPClient192.169.41.139 LVS 192.168.41.134192.169.41.10RS1192.168.41.135RS2192.168.41.138 要求: node4为客户端,node2为LVS,node3和node4为RS。 1.配置DNS解析(我这里使用本地解析) 192.168.41.134 www.y…

一、8.分页

当物理内存不够时就把不常用的内存暂时存入磁盘,并且描述符的P位置0,把要使用的段放入内存,描述符P位置1 但是这种方式会产生大量内存碎片,影响内存分配效率 设想一个虚拟内存,每隔任务都有他独立的虚拟内存&#xf…

golang pprof 监控系列—— cpu 占用率 统计原理

经过前面的几节对pprof的介绍,对pprof统计的原理算是掌握了七八十了,我们对memory,block,mutex,trace,goroutine,threadcreate这些维度的统计原理都进行了分析,但唯独还没有分析pprof 工具是如何统计cpu使用情况的,今天我们来分析…

[Pytorch]卷积运算conv2d

文章目录 [Pytorch]卷积运算conv2d一.F.Conv2d二.nn.Conv2d三.nn.Conv2d的运算过程 [Pytorch]卷积运算conv2d 一.F.Conv2d torch.nn.functional.Conv2d()的详细参数: conv2d(input: Tensor, weight: Tensor, bias: Optional[Tensor]None, stride: Union[_int, _s…

常见Charles在Windows10抓包乱码问题

废话不多说 直接开整 最近反复安装证书还是乱码 网上各种百度还是不行 首先计算机查看安装好的证书 certmgr.msc 找到并删除掉 重新安装证书 具体解决方法: 第一步:点击 【工具栏–>Proxy–>SSL Proxying Settings…】 第二步:配置…

C++路线(全网20篇高赞文章总结)

为节省时间,可直接跳转到 --> 🌼干货 目录 🌼前言 🌼来源 🐖现状 🌼干货 入门阶段 入门项目 学习顺序 🐉大二打算 🌼前言 来源的20篇博客,视频中&#x…

XML约束和解析

文章目录 概述使用场景语法dtd约束Schema约束解析DOM4j(重点) 概述 可扩展的标记性语言 使用场景 以前: 传输数据的媒介。 例如:微服务架构中,可以用xml文件进行多语言之间的的联系。 现在: 做配置文件 现在作为传输数据的媒介…

【java】使用maven完成一个servlet项目

一、创建项目 创建一个maven项目 maven是一个管理java项目的工具,根据maven的pom.xml可以引入各种依赖,插件。 步骤 打开idea,点击新建项目 点击创建项目,项目创建就完成了 进入时会自动打开pom.xml文件。 pom是项目的配置文件…

css, resize 拖拉宽度

效果如下&#xff1a; 可直接复制预览查看属性值: 关键样式属性&#xff1a; resize: horizontal; overflow-x: auto; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content…

【一次调频】考虑储能电池参与一次调频技术经济模型的容量配置方法(Matlab代码实现)

目录 &#x1f4a5;1 概述 1.1 文献来源 1.2 储能电池参与一次调频的方法 1.3 流程图 &#x1f4da;2 运行结果 2.1 数据 2.2 文献结果 2.3 复现结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码、数据、文章讲解 &#x1f4a5;1 概述 1.1 文献来源 摘要&#xff1a;规…

【学习笔记】Java安全之反序列化

文章目录 反序列化方法的对比PHP的反序列化Java的反序列化Python反序列化 URLDNS链利用链分析触发DNS请求 CommonCollections1利用链利用TransformedMap构造POC利用LazyMap构造POCCommonsCollections6 利用链 最近在学习Phith0n师傅的知识星球的Java安全漫谈系列&#xff0c;随…

Django实现音乐网站 ⑶

使用Python Django框架制作一个音乐网站&#xff0c;在系列文章2的基础上继续开发&#xff0c; 本篇主要是后台单曲、专辑、首页轮播图表模块开发。 目录 后台单曲、专辑表模块开发 表结构设计 单曲表&#xff08;singe&#xff09;结构 专辑表&#xff08;album&#xff0…

K8s集群安全机制(RBAC)

RBAC 基于角色的访问控制

MacBook触控板窗口管理 Swish for Mac

Swish for Mac是一款用于通过手势来控制mac应用窗口的软件&#xff0c;你可以通过这款软件在触控板上进行手势控制&#xff0c;你可以在使用前预设好不同手势的功能&#xff0c;然后就能直接通过这些手势让窗口按照你想要的方式进行变动了 Swish 支持 Haptick Feedback 震动反…

是什么让科大讯飞1个月股价翻倍?

目录 1、讯飞星火认知大模型的特点 2、讯飞星火认知大模型有多强大&#xff1f; 2.1、语言理解方面 2.2、知识问答方面 2.3、逻辑推理方面 2.4、数学题解答方面 2.5、代码理解与编写方面 3、如何使用讯飞星火认知大模型&#xff1f; 4、总结 我关注科大讯飞源于2021年…