C语言-指针详解速成

1.指针是什么

C语言指针是一种特殊的变量,用于存储内存地址。它可以指向其他变量或者其他数据结构,通过指针可以直接访问或修改存储在指定地址的值。指针可以帮助我们在程序中动态地分配和释放内存,以及进行复杂的数据操作。在C语言中,指针操作是一项重要的基本操作,掌握指针的使用对于编写高效的C语言程序非常重要。

说通俗点:

1.指针是内存中一个最小单元的编号,也就是地址2.平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量总结:指针就是地址,口语中说的指针通常指的是指针变量。(把内存单元的编号就称为地址(地址也叫指针)指针其实就是地址,地址就是编号指针就是内存单元的编号)

指针和指针变量:

 a01492d931ec43629b966248188f8614.png   

2.指针和指针类型

  • int p; -- 这是一个普通的整型变量
  •  int *p; -- 首先从 p 处开始,先与 * 结合,所以说明 p 是一个指针, 然后再与 int 结合, 说明指针所指向的内容的类型为 int 型。所以 p 是一个返回整型数据的指针。
  •  int p[3] -- 首先从 p 处开始,先与 [] 结合,说明 p 是一个数组, 然后与 int 结合, 说明数组里的元素是整型的, 所以 p 是一个由整型数据组成的数组。
  •  int *p[3]; -- 首先从 p 处开始, 先与 [] 结合,因为其优先级比 * 高,所以 p 是一个数组, 然后再与 * 结合, 说明数组里的元素是指针类型, 然后再与 int 结合, 说明指针所指向的内容的类型是整型的, 所以 p 是一个由返回整型数据的指针所组成的数组。
  •  int (*p)[3]; -- 首先从 p 处开始, 先与 * 结合,说明 p 是一个指针然后再与 [] 结合(与"()"这步可以忽略,只是为了改变优先级), 说明指针所指向的内容是一个数组, 然后再与int 结合, 说明数组里的元素是整型的。所以 p 是一个指向由整型数据组成的数组的指针。
  •  int **p; -- 首先从 p 开始, 先与 * 结合, 说是 p 是一个指针, 然后再与 * 结合, 说明指针所指向的元素是指针, 然后再与 int 结合, 说明该指针所指向的元素是整型数据。由于二级指针以及更高级的指针极少用在复杂的类型中, 所以后面更复杂的类型我们就不考虑多级指针了, 最多只考虑一级指针。
  •  int p(int); -- 从 p 处起,先与 () 结合, 说明 p 是一个函数, 然后进入 () 里分析, 说明该函数有一个整型变量的参数, 然后再与外面的 int 结合, 说明函数的返回值是一个整型数据。
  •  int (*p)(int); -- 从 p 处开始, 先与指针结合, 说明 p 是一个指针, 然后与()结合, 说明指针指向的是一个函数, 然后再与()里的 int 结合, 说明函数有一个int 型的参数, 再与最外层的 int 结合, 说明函数的返回类型是整型, 所以 p 是一个指向有一个整型参数且返回类型为整型的函数的指针。
  •  int *(*p(int))[3]; -- 可以先跳过, 不看这个类型, 过于复杂从 p 开始,先与 () 结合, 说明 p 是一个函数, 然后进入 () 里面, 与 int 结合, 说明函数有一个整型变量参数, 然后再与外面的 * 结合, 说明函数返回的是一个指针, 然后到最外面一层, 先与[]结合, 说明返回的指针指向的是一个数组, 然后再与 * 结合, 说明数组里的元素是指针, 然后再与 int 结合, 说明指针指向的内容是整型数据。所以 p 是一个参数为一个整数据且返回一个指向由整型指针变量组成的数组的指针变量的函数。


3. 尚未初始化的指针的含义

未初始化的指针变量就是“野”指针,它指向的是无效的地址。

出现野指针最典型的情形就是在定义指针变量之后没有对它进行初始化

指针指向某个对象之后,当这个对象的生命周期已经结束,对象已经消亡后,仍使用指针访问该对象,将出现运行时错误。考察如下程序。

#include <stdio.h>
int main(){
int*p;//指针未初始化,默认就是随机值printf("p=%d\n",*p);
//p是一个野指针,现在给他赋值可能会把它指向的内存区域数据破坏//会出现原本有用的内存数据被打乱 了。
*p=10;
printf("p=%d\n",*p);      return 0;

4. 指针运算

指针运算是针对指针(变量存储地址的变量)进行的运算操作。在程序中,指针可以通过加减操作来改变其值,这种操作就是指针运算。常见的指针运算有以下几种:

  1. 指针加法运算:可以将指针的值增加或减少若干个单位。例如,p + n 表示指针 p 的值增加 n 个单位,而 p - n 则表示指针 p 的值减少 n 个单位。

  2. 指针的自增和自减运算:可以将指针的值增加或减少一个单位。例如,p++ 表示指针 p 的值增加一个单位,而 p-- 则表示指针 p 的值减少一个单位。

  3. 指针的比较运算:可以比较两个指针的大小关系。例如,p1 > p2 表示指针 p1 的值大于指针 p2 的值,而 p1 < p2 则表示指针 p1 的值小于指针 p2 的值。

指针运算在许多编程语言中都是一种常见的操作,它可以用于实现数组、链表等数据结构,也可以用于动态内存分配和管理。但是需要注意的是,在进行指针运算时,要保证指针所指向的内存单元是有效的,否则可能会导致程序出现错误。

例1

0d87bef482674263b9cee39fcff96f09.png
5.指针和数组

指针与数组的关系

 1.当一个指针变量被初始化成数组名时,就说该指针变量指向了数组。如:

 

format,png

ptr被置为数组str的第一个元素的地址,因为数组名就是该数组的首地址,也是数组第一个元素的地址。此时可以认为指针ptr就是数组str(反之不成立),这样原来对数组的处理都可以用指针来实现。如对数组元素的访问,既可以用下标变量访问,也可以用指针访问。

2.指向数组元素的指针

  若有如下定义:

 

format,png

则pa=&a[0]是将数组第1个元素的地址赋给了指针变量pa。

实际上,C语言中数组名就是数组的首地址,所以第一个元素的地址可以用两种方法获得:pa=&a[0]或pa=a。

这两种方法在形式上相像,其区别在于:pa是指针变量,a是数组名。值得注意的是:pa是一个可以变化的指针变量,而a是一个常数。因为数组一经被说明,数组的地址也就是固定的,因此a是不能变化的,不允许使用a++、++a或语句a+=10,而pa++、++pa、pa+=10则是正确的。由此可见,此时指针与数组融为一体。

    例2

数组a中元素用下标表示为:
int *p = a;
*p,*(p+1),*(p+2),*(p+3),*(p+4)

①既然p是指向数组第一个元素起始地址的指针,可以用*(p+I)表示数组中第1+1个元索,a也是指向数组第一个元素的指针啊,那么能不能用*(a+1)表示第1+1个元素呢?
可以的,可以用printf 打印 *(a+i)的值验证
(②)反过来,a是指向数组第一个元素起始地址的指针,可以用a加数组下标引用数组元素,如a[3],p也是指向数组第一个元素起始地址的指
能不能用p加数组下标引用数组元素?计,也是可以的,可以用printf 打印 p[0],p[1]....的值验证PS: 由上得,数组名a和指针p是一样的。实际上编译时,数组元素a[i] 就是当作*(a+i)去处理的,先通过数组名a找到数组的首地址,然后首地址 a+i 得到元素a[i]的地址,
再然后通过*(a+i)得到第1个元素的内容。
所以:数组的第!个元索直接写成*(a+1)的形式直接取得值,效率不就提升了吗。省去编译器先通过数组名a找到数组的首地址,然后首地址 a+i 得到元素a[i]的地址,
再然后通过*(a+1)得到第1个元素的内容

6.二级指针

指针 可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。 如果一个指针指向的是另外一个指针,我们就称它为 二级指针 ,或者 指向指针的指针 。

800ed7d539d4407aad2bed12339d45e8.jpeg
 

 

 

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

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

相关文章

【尚硅谷】MybatisPlus 学习笔记(下)

目录 六、插件 6.1、分页插件 6.1.1、添加配置类 6.1.2、测试 6.2、xml自定义分页 6.2.1、UserMapper中定义接口方法 6.2.2、UserMapper.xml中编写SQL 6.2.3、测试 6.3、乐观锁 6.3.1、场景 6.3.2、乐观锁与悲观锁 6.3.3、模拟修改冲突 数据库中增加商品表 添加数…

❤ hexo主题+Gitee搭建个人博客

Hexo的基本使用 1. ​认识 官网 官网地址&#xff1a;https://hexo.io/zh-cn/ 介绍 Hexo是一个快速、简洁且高效的博客框架。Hexo 使用 Markdown&#xff08;或其他渲染引擎&#xff09;解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。即把用…

Ansible 更换aliyun 镜像 并下载tree

目录 查看系统版本找到对应 的版本对当前镜像进行备份下载aliyuan更换成功安装扩展源更换源之后 的三个命令 这里安装一个aliyun 的镜像 本案例 仅供实验参考 生产环境中请谨慎使用 查看系统版本 先查看linux 的系统 版本 ansible slave -m shell -a uname -a找到对应 的版本…

基于Mapbox展示GDAL处理的3D行政区划展示实践

目录 前言 一、Gdal数据处理 1、数据展示 2、Java数据转换 二、Mapbox可视化 1、定义Mapbox地图 2、地图初始化 3、创建地图 三、界面优化 1、区域颜色设置 2、高度自适应和边界区分 3、中文标注 总结 前言 最近有遇到一个需求&#xff0c;用户想在地图上把行政区划…

Android相机调用-libusbCamera【外接摄像头】【USB摄像头】 【多摄像头预览】

有的自定义系统&#xff0c;对于自己外接的USB摄像头&#xff0c;android原生的camera和camera2都无法打开&#xff0c;CameraX也用不了。这时候就要用libusbCamera&#xff0c;这个库可以打开摄像头&#xff0c;还可以多摄像头同时预览。本文主要是同时打开3个USB摄像头的项目…

《Docker 简易速速上手小册》第2章 容器和镜像(2024 最新版)

文章目录 2.1 理解 Docker 容器2.1.1 重点基础知识2.1.2 重点案例&#xff1a;使用 Docker 运行 Python 应用2.1.3 拓展案例 1&#xff1a;Docker 中的 Flask 应用2.1.4 拓展案例 2&#xff1a;Docker 容器中的数据分析 2.2 创建与管理 Docker 镜像2.2.1 重点基础知识2.2.2 重点…

异步框架Celery在Django中的运用

参考博客&#xff1a;https://www.cnblogs.com/pyedu/p/12461819.html 参考视频&#xff1a;01 celery的工作机制_哔哩哔哩_bilibili 定义&#xff1a;简单灵活、处理大量消息的分布式系统&#xff0c;专注于实时处理异步队列&#xff0c;支持任务调度 主要架构&#xff1a; …

5分钟JavaScript快速入门

目录 一.JavaScript基础语法 二.JavaScript的引入方式 三.JavaScript中的数组 四.BOM对象集合 五.DOM对象集合 六.事件监听 使用addEventListener()方法添加事件监听器 使用onX属性直接指定事件处理函数 使用removeEventListener()方法移除事件监听器 一.JavaScript基础…

Linux日志轮替

文章目录 1. 基本介绍2. 日志轮替文件命名3. logrotate 配置文件4. 把自己的日志加入日志轮替5. 日志轮替机制原理6. 查看内存日志 1. 基本介绍 日志轮替就是把旧的日志文件移动并改名&#xff0c;同时建立新的空日志文件&#xff0c;当旧日志文件超出保存的范围之后&#xff…

Git基本指令

从远程拉代码 git clone gitgitlab-internal.wedobest.com.cn:dengyanhui/gittest.git添加所有文件到待上传列表 git add .提交 git commit -m message推送 git push获取现在的状态 git status更新本地代码 git pullgit拉取某一分支代码 git clone -b develop XXX本地删除…

开源博客项目Blog .NET Core源码学习(9:Autofac使用浅析)

开源博客项目Blog使用Autofac注册并管理组件和服务&#xff0c;Autofac是面向.net 的开源IOC容器&#xff0c;支持通过接口、实例、程序集等方式注册组件和服务&#xff0c;同时支持属性注入、方法注入等注入方式。本文学习并记录Blog项目中Autofac的使用方式。   整个Blog解…

视频推拉流EasyDSS视频直播点播平台授权出现激活码无效并报错400是什么原因?

视频推拉流EasyDSS视频直播点播平台集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体&#xff0c;可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务&#xff0c;在应用场景上&#xff0c;平台可以运用在互联网教育、在线课堂、游戏…

CSS学习(三)

目录&#xff1a; 1. CSS引入方式 1.1 三种样式表 1.2 内部样式表&#xff08;嵌入式引入&#xff09; 1.3 行内样式表&#xff08;内联样式表&#xff09; 1.4 外部样式表 1.5 总结 1. CSS引入方式 1.1 三种样式表 1.2 内部样式表&#xff08;嵌入式引入&#xff09; …

7.(数据结构)堆

7.1 相关概念 堆&#xff08;Heap&#xff09;在计算机科学中是一种特殊的数据结构&#xff0c;它通常被实现为一个可以看作完全二叉树的数组对象。以下是一些关于堆的基本概念&#xff1a; 数据结构&#xff1a; 堆是一个优先队列的抽象数据类型实现&#xff0c;通过完全二叉树…

unity ui界面优化

优化一个比较复杂的界面&#xff0c;里面有多个rt和组件。 在初次打开这个界面的时候会发生1s多的卡顿&#xff0c;还是非常严重的。 分析 通过profiler分析 1.打开界面时卡顿。 分析&#xff1a;除了update和dotween相关逻辑&#xff0c;主要在于打开时的lua function调用…

svn客户端下载、安装、使用

下载、使用 打开360软件管家&#xff0c;选怎宝库&#xff0c;搜索svn&#xff0c;点击安装 可以修改安装路径 使用 在桌面右键弹出菜单&#xff0c;点击 输入地址&#xff0c;点击ok 输入用户名、密码 &#xff0c;等待检出完成

【web】nginx+php环境搭建-关键点(简版)

一、nginx和php常用命令 命令功能Nginxphp-fpm启动systemctl start nginxsystemctl start php-fpm停止systemctl stop nginxsystemctl stop php-fpm重启systemctl restart nginxsystemctl restart php-fpm查看启动状态systemctl status nginxsystemctl status php-fpm开机自启…

3ds Max视频怎么渲染 3ds Max云渲染操作

在3ds Max软件中制作视频动画本质上是逐帧生成画面&#xff0c;并将这些连续帧串联起来创造出动态连贯的视觉效果。常见的视频帧率包括25 FPS(每秒帧数)、60 FPS、以及120 FPS等&#xff0c;帧率的提升可以使视频动画更加流畅。在实质上&#xff0c;视频渲染就是动画渲染&#…

uniapp-提现功能(demo)

页面布局 提现页面 有一个输入框 一个提现按钮 一段提现全部的文字 首先用v-model 和data内的数据双向绑定 输入框逻辑分析 输入框的逻辑 为了符合日常输出 所以要对输入框加一些条件限制 因为是提现 所以对输入的字符做筛选,只允许出现小数点和数字 这里用正则实现的 小数点…

Linux--自定义shell

shell shell就是操作系统提供给用户与操作系统进行交互的命令行界面。它可以理解为一个用户与操作系统之间的接口&#xff0c;用户可以通过输入命令来执行各种操作&#xff0c;如文件管理、进程控制、软件安装等。Shell还可以通过脚本编程实现自动化任务。 常见的Unix系统中使…