第7章 地址和指针 7.1 地址和指针的概念 7.2 指针变量的定义和指针变量的基类型 7.3 给指针变量赋值 7.4 对指针变量的操作

Slides:



Advertisements
Similar presentations
2.5 函数的微分 一、问题的提出 二、微分的定义 三、可微的条件 四、微分的几何意义 五、微分的求法 六、小结.
Advertisements

第九章 指针 西安工程大学.
第七章 指针 计算机公共教学部.
第六章 指针 指针的概念 指针变量 指针与数组 指针与函数 返回指针值的函数.
二级指针与二维数组.
C语言程序设计基础 第10章 指针进阶 刘新国.
10.1 二级指针 10.2 指针与二维数组 10.3 指针的动态存储分配 10.4 函数指针 10.5 main函数的参数
第 6 章 第 6 章 指 针 指 针 1.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
1.7.1 指针和指针变量 int i = 5; int *p = &i; C++中定义一个指针变量可按下列格式:
C语言实验 第一课 标题:学号+姓名.
8.1 指针的概念 8.2 指针变量 8.3 指针变量的基础类型 8.4 指针的运算 8.5 指针与一维数组 8.6 指针应用实例
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
在PHP和MYSQL中实现完美的中文显示
4.3函数 4.3.1函数的概念及定义 1、函数的概念: 可以被其它程序调用具有 特定功能的一段相对独立的 程序(模块),称函数。
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第 十 章 指 针.
管理信息结构SMI.
走进编程 程序的顺序结构(二).
辅导课程六.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
二维数组的指针表示 与复杂的指针例子 专题研讨课之三.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第六章 指针 指针的概念 指针的运算 指向变量的指针 指向数组的指针 指向函数的指针 二级指针 主讲:李祥 时间:2015年10月.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
28.1 锐角三角函数(2) ——余弦、正切.
2.1.2 空间中直线与直线 之间的位置关系.
C++大学基础教程 第6章 指针和引用 北京科技大学 信息基础科学系.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
1.3 C语言的语句和关键字 一、C语言的语句 与其它高级语言一样,C语言也是利用函数体中的可执行 语句,向计算机系统发出操作命令。按照语句功能或构成的不 同,可将C语言的语句分为五类。 goto, return.
C语言程序设计 主讲教师:陆幼利.
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
线 性 代 数 厦门大学线性代数教学组 2019年4月24日6时8分 / 45.
C语言大学实用教程 第7章 指针 西南财经大学经济信息工程学院 刘家芬
指针 几个概念:  指针也是一种数据类型,具有指针类型的变量,称为指针变量。
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第6讲 指针与引用 6.1 指针 6.2 引用.
<编程达人入门课程> 本节内容 内存的使用 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群: ,
C语言程序设计 第一章 数据类型, 运算符与表达式 第二章 顺序程序设计 第三章 选择结构程序设计 第四章 循环控制 第五章 数组.
成绩是怎么算出来的? 16级第一学期半期考试成绩 班级 姓名 语文 数学 英语 政治 历史 地理 物理 化学 生物 总分 1 张三1 115
信号量(Semaphore).
第4章 Excel电子表格制作软件 4.4 函数(一).
第九节 赋值运算符和赋值表达式.
3.16 枚举算法及其程序实现 ——数组的作用.
第二章 类型、对象、运算符和表达式.
本节内容 结构体 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第4课时 绝对值.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
2.6 字符型数据 一、 字符常量 1、字符常量的定义 用一对单引号括起来的单个字符,称为字符常量。 例如,‘A’、‘1’、‘+’等。
C程序设计 实验二 数据类型、运算符和表达式 第6讲
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第二节 函数的极限 一、函数极限的定义 二、函数极限的性质 三、小结 思考题.
本节内容 结构体.
程序设计基础A(C语言) 第一章 C语言概述 主讲教师: 许 康
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
本节内容 动态链接库 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C语言程序设计 第8章 指针.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
基本知识 数据类型、变量、常量、运算符.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
鸡兔同笼(续) ——选择结构.
第八章 指 针 北京邮电大学出版社.
第四章 UNIX文件系统.
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
<编程达人入门课程> 本节内容 有符号数与无符号数 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
Presentation transcript:

第7章 地址和指针 7.1 地址和指针的概念 7.2 指针变量的定义和指针变量的基类型 7.3 给指针变量赋值 7.4 对指针变量的操作 第7章 地址和指针 7.1 地址和指针的概念 7.2 指针变量的定义和指针变量的基类型 7.3 给指针变量赋值 7.4 对指针变量的操作 7.5 指针在函数方面的应用

7.1 地址和指针的概念 7.1.1 地址和指针的概念 1.“地址”的概念 2.存储单元“地址”的表示 3.“指针”的概念

7.1.2 为什么使用指针 使用指针,实现了“间接访问”变量,这只是一个过程,其实质是可以达到方便地引用数组,提高计算机的运行效率,调用函数时可以修改或返回多个参数值,还可以描述更复杂的数据结构,……为了加深读者对指针重要性的理解,下面我们举一函数调用的实例。

例7.1 欲想调用fun函数,计算出两个数相加和相减的值,然后在main函数中显示结果。 程序如下: fun ( int x , int y ) { int add=0 , sub=0 ; add=x+y ; sub=x–y ; }

main ( ) { int a , b , add=0 , sub=0 ; scanf ( " %d %d " , &a , &b ) ; printf ( " a=%d , b=%d \n " , a , b ) ; fun ( a , b ) ; printf ( " %d + %d =%d \n " , a , b , add ) ; printf ( " %d – %d =%d \n " , a , b , sub ) ; }

假设程序运行时给变量a输入8,给变量b输入5,程序运行结果: 8 + 5=0 8 – 5=0

程序运行结果与我们“想象”的不一致,为什么呢?其原因是fun 函数中变量add和sub与main函数中变量add和sub各自占用自己的存储单元,因此fun函数中变量add存放的两个数的求和值无法传回到main函数的变量add中,同理,fun函数中变量sub存放的两个数的相减值也无法传回到main函数的变量中。下面我们修改一下源程序,借助指针,将fun函数中运行的结果传回到main函数中。

类型名 *指针变量名1,*指针变量名2,……; 7.2 指针变量的定义和指针变量的基类型 7.2.1 指针变量的定义和指针 变量的基类型 定义指针变量的一般形式如下: 类型名 *指针变量名1,*指针变量名2,……;

例如:int *pi , *pj ; 以上定义语句中,pi和pj都是用户标识符,表示具体的变量名,现在每个变量名前加一星号“*”说明符,用来说明所定义的变量是指针变量。 注意:变量名前的星号“*”不可省略,若省略了星号“*”说明符,就变成了普通整型变量。

int是数据类型名,在这里,说明了pi和pj是两个指向整型(int类型)变量的指针,也就是说变量pi和pj中只能存放int类型变量的地址,这时我们称int是指针变量pi和pj的基类型。又如: double *pd ; char *s1 , *s2 ;

在这里定义了三个指针变量pd、s1和s2,其中指针变量pd的基类型为double类型,在指针变量pd中,只能存放double类型变量的地址,指针变量s1和s2的基类型为char类型,在指针变量s1和s2中只能存放char类型变量的地址。又如: int **p ;

以上是定义了一个指向指针的指针变量p,该指针变量p只能存放基类型为int类型的指针变量的地址。又如: int *pi , **p , k ; 以上语句是在同一语句中,同时定义了指针变量pi、指向指针的指针变量p和变量k,这是允许的。

7.2.2 指针变量的基类型的作用 任何一个指针变量都是用于存放它所指向变量的地址,只要能存放地址就可以了,为何还要区别不同的基类型呢? 7.2.2 指针变量的基类型的作用 任何一个指针变量都是用于存放它所指向变量的地址,只要能存放地址就可以了,为何还要区别不同的基类型呢? 其原理是:不同的数据类型变量,C语言系统为它们开辟的存储空间的字节数是不同的,

int类型的数据存储空间是2个字节,float类型的数据存储空间是4个字节,……,系统表示每一个存储空间的地址时,是取该存储空间的第1个字节的地址作为该变量存储空间的地址。那么当一个基类型为int类型的指针变量p指向了一个int类型的变量a时,是将该变量a所占的2个字节的存储空间中的第1个字节存储空间的“地址”存入指针变量p中,如图7-2(b)所示。

图7-2 指针和指针所指向的对象

所以根据指针变量p中存放的“地址”,只能寻找到变量a第1个字节的存储空间,如果只提取变量a所占存储空间第1个字节的数据,显而易见不是int类型变量a的原值,因为变量a的原值是通过2个字节来存储的数据。此时我们可以通过指针变量p的基类型解决问题,知道了变量a的第1个字节的地址,再根据指针变量p的基类型为int类型,系统就将从变量a的第1个字节所在的地址开始,连续提取2个字节中的数据,此时的数据就是int类型变量a的原值。

同理,基类型为float类型的指针变量,根据指针变量中存放float类型变量的地址值,可以寻找到所需存储空间中的第1个字节所在位置,然后再根据基类型为float类型,连续地提取4个字节中的数据,作为被访问的数据,这才是float类型变量中存放的真实数据。由此,我们可以看到指针变量在定义时,其基类型是何等的重要。因此,定义什么样的基类型指针变量,该指针变量只能存放什么样类型变量的地址,两者必须一致,否则就可能出现了张冠李戴的错误现象。

7.3 给指针变量赋值 7.3.1 使指针指向一个对象 1.通过求地址运算符(&)把 一个变量的地址赋给指针变量 7.3 给指针变量赋值 7.3.1 使指针指向一个对象 1.通过求地址运算符(&)把 一个变量的地址赋给指针变量 “&”是求地址运算符,该运算符为单目运算符,用于求变量的地址,且该变量必须为内存变量。

例如:int k=1 , j =2 , *q1 , *q2 , *p ; float x=4.5 ; q1=&k ; q2=&j ;

以上第三条语句,是把变量k的地址赋给了指针变量q1,使指针变量q1中存放了变量k的地址,或称指针变量q1指向了变量k。同理,以上第四条语句,是把变量j的地址赋给了指针变量q2,使指针变量q2中存放了变量j的地址,或称指针变量q2指向了变量j。

注意:在使用 & 运算符求变量的地址,并赋给指针变量时,一定要确保所求地址的变量数据类型与存放该变量地址的指针变量基类型一致。 接上例,如执行 p=&x ; 语句,则是绝对错误的。为什么?请读者想一想!

读者还记得在前面调用 scanf 函数时,其函数调用格式中,输入数据所对应的各变量名之前都必须加运算符 & ,这就是我们所说的求地址运算符。scanf 函数把从终端读入的数据依次放入这些地址所代表的存储单元中,也就是说scanf 函数要求输入项是地址值。因此接上例,scanf ( " %d %d " , &k , &j ) ; 语句和scanf ( " %d %d " , q1 , q2 ) ; 语句是等价的,都是将终端输入的整型数据存入到变量k和变量j所在的存储单元中。

2.同类型指针变量之间可以直 接赋值 可以把指针变量的值赋给指针变量,但一定要确保这两个指针变量的基类型是相同的。 接上例:p=q1 ; 2.同类型指针变量之间可以直 接赋值 可以把指针变量的值赋给指针变量,但一定要确保这两个指针变量的基类型是相同的。 接上例:p=q1 ; 执行以上语句后,使指针变量p也存放了变量k的地址,也就是说指针变量p和q1同时指向了变量k。

7.3.2 给指针变量赋“空”值 为了使指针变量有一确定的数值,除了给指针变量赋一地址值外,当指针变量没有指向的对象时,也可以给指针变量赋NULL值,此值为空值。例如:int *p ; p=NULL ; 表示指针变量p的值为空。

NULL是在stdio.h头文件中定义的预定义符,因此在使用NULL时,应该在程序的前面出现预定义命令行:# include " stdio.h "。NULL的代码值为0,所以语句p=NULL ;等价于:p=0 ;,都是表示指针变量p是一个空指针,没有指向任何对象。

7.4 对指针变量的操作 7.4.1 通过指针或地址引用一 个存储单元 7.4 对指针变量的操作 7.4.1 通过指针或地址引用一 个存储单元 当指针变量中存放了一个确切的地址值时,通过指针可以用“间接运算符”(*)来引用该地址所代表的存储单元。

1.在赋值号右边由“*”运算符 和指针变量组成的表达式,代表指 针所指存储单元的内容 1.在赋值号右边由“*”运算符 和指针变量组成的表达式,代表指 针所指存储单元的内容 例如: int *p , i=10 , j ; p=&i ; j=*p ;

第二条语句是把变量i的地址赋给了指针变量p,第三条语句是把指针变量p所指向的变量i存储单元的值10赋给变量j。 “*”号在这里是一个“间接运算符”,它为单目运算符,与运算对象自右至左结合,且运算对象必须为一个地址对象。 例如: j=*&i ; 该语句中“&”运算符求出变量i的地址,“*”运算符取变量i地址中的值10赋给变量j。

例如: int **pp , *p , k=20 , j ; p=&k ; pp=&p ; j=**pp ; 以上语句执行后的结果是:把变量k的地址赋给了指针变量p,把指针变量p的地址赋给了指向指针的指针变量pp,这种关系如图7-4所示。最后一条语句是把变量k中的值20赋给了变量j,这条语句使用了两个“间接运算符”,**p表示获取指针变量p中的值(此值为变量k的地址值),**pp表示通过指针变量p,再获取变量k中的值20。

图7-4 变量pp、p和k之间的关系

2.在赋值号左边由“*”和指针 变量组成的表达式,代表指针所指 的存储单元 2.在赋值号左边由“*”和指针 变量组成的表达式,代表指针所指 的存储单元 例如: int *p , k=0 ; p=&k ; *p=150 ; 以上第三条语句是把整数150存入变量k中。 *p=*p +1 ; 或 *p+=1 ;

以上语句是获取指针变量p所指向的存储单元k中的值150,然后加1再放入指针变量p所指向的存储单元k中,此时变量k中存放的数值为151。 例如: int **p , *p , k ; p=&k ; pp=&p ; **pp=200 ; 以上第四条语句是将整数200存入变量k中。

例7.3 指针指向三个变量,通过指针运算选出数值最小的那个数并打印出来。 main() { int a , b , c , min , *pa , *pb , *pc , *pmin ; pa=&a ; pb=&b ; pc=&c ; pmin=&min ; scanf ( " %d %d %d " , pa , pb , pc ) ; /* 将键盘输入的三个整数依次放入变量a、b、c中 */

printf ( " a=%d , b=%d , c=%d \n " , a , b , c ) ; *pmin= *pa ; /* 假定变量a中的数值最小,将其放入变量min */ if (*pmin> *pb ) *pmin= *pb ; /* 若b中的数值比min小,将其放入变量min */ if (*pmin> *pc ) *pmin= *pc ; /* 若c中的数值比min小,将其放入变量min */ printf ( " min=%d \n " , min ) ; /* 通过直接访问方式输出变量min中的值 */ printf ( " min=%d \n " , *pmin ) ; /* 通过间接访问方式输出变量min中的值 */ }

当运行程序时输入 25 12 36↙ 程序运行结果: a=25 , b=12 , c=36 min=12 程序运行结果说明,当指针指向变量后,可以通过指针对所指向的存储单元进行数据的存取,直接访问方式和间接访问方式的结果是相同的。

7.4.2 指针(变量)的运算 1.指针的移动 2.指针的比较

7.5 指针在函数方面的应用 7.5.1 在被调用函数中直接改 变主调用函数中的参数值 7.5 指针在函数方面的应用 7.5.1 在被调用函数中直接改 变主调用函数中的参数值 在第6章中,我们曾经介绍过,通过return语句可以返回函数值,但这种方式只能返回一个数据,若想修改或传回多个数值,可以借用指针。

7.5.2 使函数返回一个地址 一个函数运行结束时,可以返回一个整型值、实型值、字符型值等,同样也可以返回指针型的数据,即返回地址值。这种返回指针型数据的函数,定义的形式为: 类型名 *函数名(参数表) { …… } 说明:函数名前的星号“*”,说明了此函数是一个指针型函数,函数的返回值是一个地址值。