C语言中的指针:掌握内存的钥匙

news2024/12/28 20:14:01

C语言中的指针:掌握内存的钥匙

引言

       C语言是一种结构化编程语言,它提供了对硬件底层的直接访问,其中最强大的特性之一就是指针。指针允许程序员直接操作内存地址,这对于理解程序的内部工作原理以及优化代码性能至关重要。本文将深入探讨C语言中指针的概念、使用方法以及一些高级技巧。

什么是指针

       指针就是内存地址,指针变量是用来存放内存地址的变量。就像其他变量或常量一样,必须在使用指针存储其他变量地址之前,对其声明。

声明形式:

type *pointName;

其中type是指针的基类型,它必须是一个有效的C数据类型,pointName是指针变量的名称。用来声明指针的星号*与乘法中使用的星号是相同的,但是在c语句中,星号是用来指定一个变量是指针。
C语言中的指针
例如:指针简单使用
C语言中的指针
输出结果
在这里插入图片描述

指针与变量

内存区的每一个字节都有一个编号,这就是"地址",如果在程序中定义了一个变量,在对程序进行编译运行时,系统就会给这个变量分配一个内存单元,并确定它的内存地址也就是一串这个地址独有的编号,指针是内存单元的编号,指针变量是存放地址的变量,通常我们会把指针变量称为指针,其实指针与指针变量含义式不一样的。

指针变量赋值

指针变量在使用之前, 一定要先赋值,也就是让指针变量指向一个地址。注意,给指针变量赋值只能式地址,通过"&"符号来获取普通变量的地址。“&” - 取地址运算符,“*” - 指针运算符,或称为间接访问运算符,取地址的值。
例子:
在这里插入图片描述
输出结果:上面代码演示了如何在C语言中使用指针,第一步定义一个整型变量i和一个指向整型变量的指针p。然后将i的值初始化为10,并将p指向i的地址,然后打印出i,和p的内存地址以及i的值和通过指针p访问到的值。
在这里插入图片描述
i = 0x7ffd55fc953c 变量i的存储地址, p = 0x7ffd55fc953c是指针变量p指向的地址,以为代码中把i的地址赋给了p,所以p指向i的存储地址。i=10i赋值10*p = 10 指针变量p指向地址里的值,p指向的是地址0x7ffd55fc953c,而这个地址里存储的值为10,所以*p=10

通过地址取值:*((unsigned char *)p))

在这里插入图片描述
输出结果:((unsigned char *)7c3d726c))代表把 0x7c3d726c 这个值,强制转换成一个无符号字符类型指针,相当于告诉编译器,这是一个地址,强制转换的类型和变量a的数据类型保持一致,因为要通过地址,把变量i的值读出来,最后通过*把这个地址的数据读出来,结果7c3d726c = 10
在这里插入图片描述

通过指针改变某个内存地址里的值

上面说了如何获取内存地址的值,那也可以通过指针改变某个内存地址里面的值。格式: *指针变量 = 数值; 【*p = 20】
在这里插入图片描述
输出结果:
在这里插入图片描述
案例2:输入a和b两个整数,然后按先大后小顺序输出a和b。不交换整型变量的值,而是交换两个指针变量的值。
在这里插入图片描述
分析:输入a=5,b=6,由于a<b,将p1和p2交换,注意的是,a和b的值并未交换,他们仍然保持原值,但是p1和p2的值改变了,p1的值原来为&a,后来变成了&b, p2的值原来为&b后来变成了&a,这样在输出p1和p2的时候,实际上是输出了变量b和a的值,所以先输出6后输出5。
在这里插入图片描述

指针变量作为函数参数

函数的参数不仅可以是整型,浮点型,字符型,还可以是指针类型,它的作用将一个变量的地址传送到另一个函数中。

案例:通过指针类型的数据作为函数的参数,对输入的两个整数按大小顺序输出。【通过指针实现交换两个变量的值】
在这里插入图片描述
案例:输入三个整数a,b,c,要求按由大到小的顺序输出。
在这里插入图片描述

指针与一维数组

一个变量有地址,一个数组包含若干个元素,每个数组元素都在内存中占有存储单元,它们都有相应的地址,指针变量既然可以指向变量,当然也可以指向数组元素,把某一元素的地址放到一个指针变量中,所谓的数组元素的指针就是数组元素的地址。c语言定义数组时,编译器会分配连续地址的内存,来存储数组里的元素,实际上数组本质上也是指针。

分别打印了arr&arr[0]的地址,发现地址是一样的,既然是个地址,那就可以使用指针的形式,去访问地址里存储的值,然后打印*arr的值,得到的结果为1,正好和arr[0]的值对应,最后得出数组也可以使用指针的形式去使用。

数组元素的引用

        引用数组元素可以使用下标法,也可以使用指针法,即通过指向数组元素的指针找到所需的元素。使用指针法能使程序质量高,占用内存少,运行速度快。

	p = &a; // p的值是a[0]的地址
	p = a; // p的值是数组a首元素即a[0]的地址

在这里插入图片描述
注意:程序中的数组名不代表整个数组,只代表数组首元素的地址。上面的p = a的作用是把a数组首元素的地址赋给指针变量p,而不是把数组a各元素的值赋给p,可以简写为 int *p = &a[0];也可以写成int *p = a; 也可以写成两行的形式int *p; p = &a[0];他们都有一个作用:将a数组首元素即a[0]的地址赋给指针变量p(而不是*p)。
在这里插入图片描述

  • 下标法 a[i]的形式
  • 指针法如*(a+i)*(p+i)。其中a是数组名,p是指向数组元素的指针变量。
    在这里插入图片描述
    或者用指针变量指向数组元素
    在这里插入图片描述
    注意:在使用指针变量指向数组元素的时候,可以通过改变指针变量的值指向不同的元素,例如上面代码中的方法是使用指针变量p来指向元素,用p++使p的值不断改变宠儿指向不同的元素。
    换一种想法,如果不用p变化的方法而用数组名a变化的方法如a++行不行呢。for(p=a;a<(p+10);a++) printf("%d",*a);答案是不行的,因为数组名a代表数组首个元素的地址,他是一个指针型常量,它的值在程序运行期间是固定不变的,既然a是常量,所以a++是无法实现的。
    例:通过指针变量输出整型数组a的10个元素。
    在这里插入图片描述
    很明显,输出的数值并不是a数组中各个元素的值,因为在执行第二个for循环读入数据后,p已指向a数组的末尾,因此在执行第二个for循环时候,p的起始值不是&a[0]了,而是a+10
    在这里插入图片描述
    解决上面问题只要在第二个for循环之前加一个赋值语句即可
    在这里插入图片描述

常用指针引用数组元素的情况

  • (1) p++; p; p++使p指向下一个元素a[i],然后再执行p,则得到下一个元素a[i]的值。
  • (2) p++; 由于++和同优先级,结合方向为自右而左,因此它等价于*(p++)。先引用p的值,实现*p的运算,然后再使p自增1。
  • (3) (p++)与(++p)作用,前者先取p值,然后使p加1。后者是先使p加1,再取p。若初始值为a即&a[0],若输出*(p++)得到a[0]的值,而输出*(++p)得到a[1]的值。
  • (4) ++(*p) 表示p所指向的元素值加1,如果p = a,则++(*p)相当于++a[0],若a[0]的值为3,则在执行++(*p)即++a[0]后的值为4。
  • (5) 如果p当前指向a数组中第i个元素a[i],则:
            *(p--) 相当于a[i--],先对p进行运算(求p所指向的元素的值),再使p自减。
            *(++p) 相当于a[++i],先使p自加,在进行
    运算。
            *(--p) 相当于a[–i],先使p自减,再进行*运算。
    将++和–运算符用于指针变量十分有效,可以使指针变量自动向前或向后移动,指向下一个或上一个数组元素。

持续更新中。。。

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

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

相关文章

python如何判断变量是否可迭代

python如何判断变量是否可迭代&#xff1f;方法如下&#xff1a; 方法一&#xff1a; 适用于python2和python3 >>> from collections import Iterable >>> isinstance("str", Iterable) True 方法二&#xff1a; 适用于python3 s "hello …

『 Linux 』命名管道

文章目录 命名管道与匿名管道命名管道特点命名管道的理解命名管道实现两个毫无关联的进程间通信 命名管道与匿名管道 命名管道是管道的一种,数据流向为单向故被称为管道; 与匿名管道相同属于一种内存级文件; 区别如下: 名字 匿名管道 没有名字,只存在于内存当中(类似内核缓冲…

【Visual Studio】Visual Studio使用技巧及报错解决合集

目录 目录 一.概述 二.Visual Studio报错问题及解决方法 三.Visual Studio操作过程中遇到的问题及解决方法 四.Visual Studio编译优化选项 五.Visual Studio快捷键 一.概述 持续更新Visual Studio报错及解决方法&#xff0c;包括Visual Studio报错问题及解决方法、Visua…

mac电脑pdf合并,macpdf合并成一个pdf

在数字化办公和学习的今天&#xff0c;pdf文件因其跨平台兼容性强、格式稳定而成为了最受欢迎的文档格式之一。但随之而来的问题也接踵而至&#xff0c;如何将多个pdf文件合并为一个&#xff1f;这不仅关系到文档的整洁性&#xff0c;更是时间管理的重要环节。今天&#xff0c;…

STM32+TMC2209控制步进电机正反转。

STM32F103ZET6TMC2209控制步进电机正反转 1. 步进电机介绍2 驱动器TMC2209介绍2.1 引脚图及其功能2.2 细分介绍2.3 TMC控制驱动器接法 3 控制器介绍3.1 确定控制引脚3.2 UBEMX配置3.2.1 GPIO配置3.2.2 NVIC配置3.2.3 RCC配置3.2.4 SYS配置3.2.5 USRAT2配置&#xff08;PS:没用上…

【JS红宝书学习笔记】第25章 客户端存储

第25章 客户端存储 Cookie HTTP是无状态的&#xff0c;也就是说&#xff0c;你这次访问服务器&#xff0c;关闭后再次访问服务器&#xff0c;服务器是意识不到又是你来访问的。 登录时&#xff0c;浏览器需要帮我们在每一次请求里加入用户名和密码&#xff0c;这样才能做到保…

(WRF-UCM)高精度城市化气象动力模拟

气候变化及应对是政府、科学界及商业界关注的焦点。气候是多个领域&#xff08;生态、水资源、风资源及碳中和等问题&#xff09;的主要驱动因素&#xff0c;合理认知气候变化有利于解释生态环境变化机理及过程&#xff0c;而了解现在、未来气候变化则是进行生态、环境及能源评…

Win11鼠标卡顿 - 解决方案

问题 使用Win11系统使&#xff0c;鼠标点击任务栏的控制中心&#xff08;如下图&#xff09;时&#xff0c;鼠标会有3秒左右的卡顿&#xff0c;同时整个显示屏幕也有一定程度的卡顿。 问题原因 排除鼠标问题&#xff1a;更换过不同类型的鼠标&#xff0c;以及不同的连接方式…

【计算机毕业设计】学生心理咨询评估系统设计与实现【源码+lw+部署文档】

包含论文源码的压缩包较大&#xff0c;请私信或者加我的绿色小软件获取 免责声明&#xff1a;资料部分来源于合法的互联网渠道收集和整理&#xff0c;部分自己学习积累成果&#xff0c;供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者…

[BJDCTF2020]EzPHP1

知识点&#xff1a;1. url编码绕过 2. %0a绕过 3. post优先级绕过 4. php伪协议 5. 数组的强类型比较绕过 6. 取反绕过 进入之后发现了一个很帅气的页面&#x1f60e;~ 看看网页源代码试试~ 是base32编码&#xff0c;尝试一下解码. https://www.qqxiuzi.cn/bianma/base.php 解…

qt 创建一个左侧边线拖拽的矩形

1.概要 2.代码 2.1 代码第一版 在Qt中&#xff0c;要创建一个可以向左侧拖拽边线的矩形&#xff0c;你需要自定义一个QGraphicsRectItem的子类&#xff0c;并重写其事件处理函数来响应鼠标的拖拽动作。以下是一个简单的实现示例&#xff1a; #include <QApplication>…

DHCP服务、FTP服务

一、DHCP 1.1 DHCP是什么 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主机配置协议&#xff09;是一种网络协议&#xff0c;用于自动分配 IP 地址和其他网络配置信息给网络中的设备 1.2 DHCP的好处 自动化: 减少了手动配置 IP 地址和网络参数的工…

C++客户端Qt开发——常用控件(多元素控件)

5.多元素控件 Qt中提供的多元素控件有&#xff1a; QListWidget QListView QTablewidget QTableview QTreewidget QTreeview xxWidget和xView之间的区别 以QTableWidget和QTableView为例. QTableView是基于MVC设计的控件.QTableView自身不持有数据.使用QTableView的时候需要…

【密码学】密码学数学基础:剩余系

不得不啃的密码学数学基础之剩余系是个啥&#xff1f;数学里面有好多的定义都有前置的数学概念&#xff0c;要想弄懂剩余系还得先说说“同余”。 一、同余 那么“同余”有是个什么呢&#xff1f;在谈论“同余”之前&#xff0c;我们先圈定个讨论的范围。接下来讨论的都是整数集…

PyTorch Autograd内部实现

优化&#xff1a;如果is_leafFalse&#xff0c;则说明不需要该Tensor的grad&#xff0c;所以&#xff0c;grad_fn直接将output梯度传递给下一个grad_fn了&#xff0c;绕开对该Tensor的grad的更新&#xff1b;

C语言 | Leetcode C语言题解之第235题二叉搜索树的最近公共祖先

题目&#xff1a; 题解&#xff1a; struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) {struct TreeNode* ancestor root;while (true) {if (p->val < ancestor->val && q->val < ancestor-&g…

信息系统项目管理师(高项)—学习笔记二

第一章 以下是上一篇&#xff08;信息系统项目管理师&#xff08;高项&#xff09;—学习笔记&#xff09;的续写&#xff0c;因为是之前记录的&#xff0c;这一篇还是细致到每一个小节的内容&#xff0c;有些过于复杂了&#xff0c;后续会简化~ 1.3 现代化创新发展 党的十九…

干货丨ChatGPT高阶玩法(上)

正文共1321字 预计阅读时间4分钟 是的,你没有看错,上面这段这么像人写的内容其实是由ChatGPT这个机器人AI生成的(我只稍加修改了几个字),发送下面第一个提示词口令,然后加以进一步引导并不断改进就可以得到你想要的结果,具体操作见文中图片。 使用说明 以下【】里的内…

Unable to obtain driver using Selenium Manager: Selenium Manager failed解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

《Windows API 每日一练》10.1 模态对话框

对话框分“模态”和“非模态”两种&#xff0c;其中模态对话框最为常见。当程序显示一个模态对话框时&#xff0c;用户不能在对话框和该程序的其他窗口之间进行切换。用户必须先明确地终止该对话框。这通常由单击OK或Cancel按钮来实现。但是当对话框正在显示时&#xff0c;用户…