




已阅读5页,还剩77页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第9章指针 特点 能直接对内存地址操作 使用灵活 实现动态存储管理 可以使程序简洁 紧凑 高效 用间接访问的方式改变数据的逻辑顺序 调用函数时可实现变量的引用传递 地址和指针的概念 变量的地址和变量的值 inti 3 floatj 6 doublek 9 3 6 0 9 0 变量i 变量j 变量k 2200 2206 2202 2214 程序中定义的变量 系统根据它的类型给它分配一定长度的内存单元 该内存单元的起始地址即为变量的地址 该内存单元的内容就是变量的值 直接访问和间接访问 直接访问 用变量名直接从它对应的地址存取内容 如 intx 5 y 8 z 0 z x y 13 直接从x和y对应的地址2200和2202取出内容5和8然后相加将结果13存入变量z对应的地址2204的单元中 间接访问 定义一个存放地址的变量p p的地址1500 将x的地址2200存放在变量p中 通过变量p取出地址2200 再按此地址存取其中的内容 就间接的完成了对x的存取 当p的内容改为2202时 通过变量p取出地址2202 再按此地址 存取的就是变量y的内容 p就是指针变量 5 8 0 变量x 变量y 变量z 2200 2202 2204 2202 指针变量的定义 一般形式 基类型名 指针变量名 说明 基类型名 指针变量所指向的变量的类型名称 指针变量名 所定义的指针变量的名称 表示它后面的变量名是指针类型 功能 1 定义该指针变量名为指向基类型的指针变量 为该变量分配存储单元 其长度等于存储地址的字节数 2 基类型确定用指针变量 间接 存取数据的存储单元个数和存储形式 该变量只能指向基类型数据 指针变量的初始化 用 变量名来给指针变量赋初值 选项中的变量名必须是已定义过的 其类型必须与基类型一致 表示将它对应的地址值赋给所定义的指针变量 例如 intx p intx p intx float p 可以用赋值语句给指针变量赋值 floaty py py 指针变量的引用 引用指针变量的指针值与引用其它类型的变量一样直接用它的变量名 引用指针变量所指向的变量时 用 指针变量名 注意 指针变量的值与它所指向变量的值之间的差别 指针变量只有正确赋值后才能通过它访问指向的变量 intx p int p p p 5 5 指针变量的运算 1 取地址运算符 取右边变量的地址 2 指向运算符 间接访问运算符 访问指针变量右边所指向的变量 a是变量a的地址 p是指针变量p指向的变量 说明 和 都是单目运算符 它们的优先级相同 按自右而左方向结合 如果已定义floata p 则 p 是变量a p 是变量a的地址p p 等价于p 而 a 是变量a的地址p a 是p所指向的变量a a 等价于a 注意 1 指针变量定义和引用指向变量的 含义有差别 2 不能引用没有赋值的指针变量 不要误认为p定义后变量 p就已存在 必须给p正确赋值后 变量 p才存在 3 p 是给p指向的变量赋值 两者含义完全不同 4 给指针变量赋值必须用同类型的指针 5 指针变量只存放地址 地址值是无符号整数 但不能直接用整型量 或其它非地址量 赋值给指针变量 int p1 2200 给变量赋值的两种方法 1 直接访问用变量名 如 inti i 5 2 间接访问通过指向变量i的地址的指针变量p赋值 如 inti p p 取地址运算符 和指向运算符 的应用 main intm n int p 运行结果 Inputm n 123456 m 123 m FFD6 p 123p FFD6n 456 n FFD8 q 456q FFD8 printf min d max d n p1 p2 main 运行结果 min 6 max 8 例 通过交换指针变量值按大小顺序输出 指针变量作为函数的参数 以指针类型为函数的参数 作用是将变量的地址传入函数 intx y int pt1 pt2 x 8 y 6 pt1 if x y s printf x d y d n x y s p1 int p2 p p1 p1 p2 p2 p intp 8 main 6 8 运行结果 x 6 y 8 intx y int pt1 pt2 x 8 y 6 pt1 if x y s s p1 int p2 p p1 p1 p2 p2 p intp printf x d y d n x y 指针与数组 C语言中规定数组名是指针类型的符号常量 该符号常量值等于数组首元素的地址 简称数组首地址 它的类型是指向数组元素的指针类型 即数组名是指向该数组首元素的指针常量 指向数组元素的指针 1 定义指向数组元素的指针变量 定义指向数组元素的指针变量与定义指向变量的指针变量的方法相同 如 inta 10 int p p 由于数组名是指向0号元素的指针类型符号常量 所以a与 a 0 相等 p 两句等价 p a不是把a的各元素赋给p 注意数组名与指针变量的区别 指针运算 指针变量可以加减一个整数 两个同类型指针可以相减得到一个整数 指针变量每增减1 地址值增减量等于所指向的变量类型的字节数sizeof type 将它称作地址步进单位d 当指针变量指向数组元素时 指针变量每加减1 表示指针前后移动1个元素 地址值增减d 如 inta 10 p p a p p 3 注意 指针变量的运算顺序 p p p p 四者之间的差别 p 先给p指向的变量加1 然后取其值 p 先取p指向的变量值 然后该变量值加1 p 取p所指向变量的值 然后p增1 p P先增1 然后取p所指向变量的值 main inta 4 1 2 3 4 b c d e int p a b p printf n d d b p c p d p printf d d c d 运行结果1 2 3 4 通过指针引用数组元素 在inta 10 p a 定义的情况下 1 p i或a i就是a i 的地址 都要进行a i d的运算 2 p i 或 a i 就是p i或a i所指向的数组元素a i 数组元素中的 是变址运算符 相当于 a i 相当于 a i 3 指向数组元素的指针变量也可带下标 如p i 与 p i 等价 所以 a i a i p i p i 四种表示法全部等价 4 注意p与a的差别 p是变量a是符号常量 不能给a赋值 语句a p a 都是错的 a 引用数组元素可用 1 下标法 如a i p i 2 指针法 如 p i 或 a i 其中p是指向数组a的元素的指针变量 main inta 10 int p i for p a p a 10 p scanf d p printf n for i 0 i 10 i printf d a i for i 0 i 10 i printf d a i p a 不能省略 for i 0 i 10 i p printf d p for p a p a 10 p printf d p 例 输入 输出数组全部元素 用字符型指针访问字符数组和字符串 例9 5 用字符型数组名和字符指针变量两种方法整体输入 输出字符串 main chars 81 Hello p s char ps Welcometoyou printf s n s printf s n ps gets s printf s n s gets p printf s n s 字符指针变量和字符数组的区别 1 存储的内容不同 字符数组存储着字符串的内容 而字符指针变量存放的是字符串首元素的地址 不是它的内容 2 分配的内存单元不同 字符数组分配一段有确定地址的内存 而指针变量只分配存放地址的内存单元 该指针变量可以指向一个字符型数据 但若未赋初值 则它并未指向一个明确的地址 此时它指向的变量并不存在 3 赋值方法不同 对字符数组只能在定义时整体赋初值 不能用赋值语句整体赋值 赋值语句只能对各个元素分开赋值 如 chars 16 s Iamastudent chars 16 Iamastudent 对字符指针变量 可以采用下面方法赋值 char p p Iamastudent 4 指针变量的值是可以改变的 字符数组名是地址常量其值是不能改变的 数组或指针变量作函数参数 如 main f inta intn intarray 10 f array 10 由于数组名代表首地址 能接收并存放地址值的只能是指针变量 故编译系统将形参数组名作为指针变量来处理 例中函数首部f inta intn 可写成f int a intn 两种完全等价 归纳起来 如果有一个数组 想在被调用的函数中改变其元素的值 实参与形参的对应关系有以下四种 1 实参和形参都用数组名 2 实参用数组名 形参用指针变量 3 实参用指针变量 形参用数组名 4 实参和形参都用指针变量 实质都是地址值的传递 例9 7 通过调用函数 将整型数组的所有元素加10 参数传递用四种方法实现 voidadd intb intn inti for i 0 i n i b i 10 main inti a 10 1 2 3 4 5 6 7 8 9 10 add a 10 for i 0 i 10 i printf 4d a i voidadd int p intn int pend p n for p pend p p 10 main inti a 10 1 2 3 4 5 6 7 8 9 10 add a 10 for i 0 i 10 i printf 4d a i voidadd intb intn inti for i 0 i n i b i 10 main inti a 10 1 2 3 4 5 6 7 8 9 10 int q a add q 10 for i 0 i 10 i printf 4d a i voidadd int p intn int pend p n for p pend p p 10 main inti a 10 1 2 3 4 5 6 7 8 9 10 int q a add q 10 for i 0 i 10 i printf 4d a i 用字符数组或指针做函数参数传递字符串 将字符串从一个函数传递到另一个函数 可以用地址传递的方法 即用字符数组名或用字符指针变量作参数 在被调用的函数中可以改变字符串中的内容 在主调函数中可以得到改变了的字符串 例9 8 字符串复制函数主要功能的实现 1 用字符数组作参数 voidstrcpy chars1 chars2 inti 0 while s2 i 0 s1 i s2 i i s2 i 0 main chara 20 Iamateacher charb youareasrudent printf stringa s nstringb s n a b strcpy a b printf nstringa s nstringb s n a b 2 形参用字符指针变量 程序如下 voidstrcpy char s1 char s2 for s2 0 s2 s1 s1 s2 s1 0 main chara 20 Iamateacher char b youareasrudent printf stringa s nstringb s n a b strcpy a b printf nstringa s nstringb s n a b while s1 s2 0 s1 s2 s1 0 while s2 0 s1 s2 s1 0 while s2 s1 s2 s1 0 while s1 s2 0 while s1 s2 多维数组和指向分数组的指针 多维数组的地址 以二维数组为例 设二维数组a有3行4列 inta 3 4 1 2 3 4 5 6 7 8 9 10 11 12 a是数组名 a数组有3行 即3个分数组 a 0 a 1 a 2 每个分数组又是含4个列元素的一维数组 2000 基类型 行指针与列指针 a 2 3 a 2 3 a 2 3 3 2 1 0 a 0 a 0 a 0 a 0 a 0 a 0 a 0 a 0 3 2 1 0 a 1 a 1 a 1 a 1 a 1 a 1 a 1 a 1 注意 a 1与a 0 1不同a 1是a第1行分数组地址 a 1 是第1行数组名 a 1 是元素a 1 0 a 0 是第0行分数组名a 0 1是元素a 0 1 地址 a 0 1 是元素a 0 1 形式含义内容a a 0 二维数组名 0行分数组地址1000a 0 a 0 a a 0 0 0行一维数组名 0行0列元素地址1000a 0 1 a 1 a 0 1 0行1列元素地址1002a 1 a 1 1行一维数组首地址1008a 1 a 1 a 1 0 1行一维数组名 1行0列元素地址1008a 1 3 a 1 3 a 1 3 1行3列元素地址1014 a 2 3 a 2 3 a 2 3 2行3列元素12注意 a和a 0 的地址均为1000但不等价 a 1和a 0 1不等 指向多维数组的指针 1 指向多维数组元素的指针 例 用指针变量输出数组元素的值 main inta 3 4 1 2 3 4 5 6 7 8 9 10 11 12 int p for p a 0 p a 0 15 p if p a 0 5 0 printf n printf 4d p 定义形式 数据类型 指针名 一维数组维数 一维数组指针变量维数和二维数组列数必须相同 例 inta 3 4 p 4 a 2 指向分数组的指针 p 0 1 p 或 p 1 p 1 2 p 1 或 p 1 2 p 2 inta 3 4 int p 4 a 例 用指向二维数组的分数组的指针变量 按行输出 main inta 3 4 1 2 3 4 5 6 7 8 9 10 11 12 int q p 4 for p a p a 3 p for q p q p 4 q printf 5d q printf n 注意 int p 5 表示p是一个指针变量 可以指向含有5个元素的一维数组 其中每个元素都是整型的 如果定义为int p 5 由于 优先级高 则表示p首先是数组 它有5个元素 每个元素为指向整型变量的指针 用多维数组名和指针变量作函数参数 1 用多维数组名作实参或形参 如 f inta 4 intn 2 用指向元素的指针变量作实参或形参 如 f1 int p 3 用指向分数组的指针变量作函数参数 如 f2 int q 4 intm 例9 16 用两个二维数组存储矩阵 调用函数求两个矩阵之差 差矩阵存放在第一个实参数组中 用指向分数组的指针变量作形参 矩阵输出也用函数实现 defineN4sub int p1 N int p2 N intm int q1 q2 u N u p1 m for p1 u p1 p2 for q1 p1 q2 p2 q1 p1 N q1 q2 q1 q2 print int p N intm int q u N u p m for p u p for q p q p N q printf 6d q printf n printf n main inti j a N 1 2 3 4 5 6 7 8 intb N 10 20 30 40 50 60 70 80 print a 2 print b 2 sub b a 2 print b 2 指针数组 如果每个数组元素均为指针类型的变量 即数组元素的类型是指针类型 则称这样的数组为指针数组 一维指针数组的定义形式为 基类型名 数组名 数组长度 地址初值列表 例如 inti j k m n int q 5 main chara Program charb Fortran charc Basic char p 4 p 0 a p 1 b p 2 c p 3 NULL char p 4 0 或 main char p 4 p 0 Program p 1 Fortran p 2 Basic p 3 NULL 初始化 main char p Program Fortran Basic NULL 用指针数组处理多个字符串 例 将5个字符串递增排序后输出 include includemain char pccolor red blue yellow green purple intn 5 printf Beforesortingis n OutPut pcolor n Sort pcolor n printf Aftersortingis n OutPut pcolor n voidSort char a intn inti j k char t for i 0 i n 1 i for j i 1 j n j k j if k i t a i a i a k a k t if strcmp a k a j 0 voidOutPut char a intn inti for i 0 i n i printf s n a i 排序前 排序后 指向指针的指针 二级指针 指针变量中存放一级指针变量的地址 例int p1 int p2 inti 3 p2 二级指针 一级指针 目标变量 二级间接寻址 p2 i 5 3 用指向指针的指针访问指针数组 通过指针变量来访问指针数组的元素 就必须定义指向指针的指针变量 用所定义的指向指针的指针变量来指向指针数组的各元素 进行间接访问 若要通过该指针变量来访问指针数组元素所指向的变量的内容 则需要进行两次间接访问 例9 10 指针数组的各元素指向整型数据的简单实例 main staticints 5 10 20 30 40 50 int q 5 指针数组作main 函数的形参 C语言规定 main 函数形参是固定的 第一个形参为整型 它接收实参的个数 第二个形参为字符指针数组 它的各元素分别接收命令行输入的各字符串的首地址 例如 main intargc char argv 形参argc接收实参的个数 字符指针数组argv接收各字符串的首地址 它的一般形式为 命令名参数1参数2 参数n 1 例9 11 编写源程序show c 在命令行输入show和若干个字符串后 顺序分行显示这些字符串 show c的程序如下 main intargc char argv inti for i 1 i argc i printf s n argv i 改写为 main intargc char argv while argc 0 printf s n argv 例9 12 编写程序echo c 实现操作系统中的echo命令 echo命令是将后面所带的参数原样显示出来 它与上例相似但不分行 所带的参数都显示在同一行 main intargc char argv while argc 0 printf s c argv argc 1 n 在操作系统命令行状态下输入 echoWelcometoyou 执行后输出以下信息 Welcometoyou 例9 18 实现系统提供的字符串复制函数strcpy 的全部功能 char strcpy char s1 char s2 char p s1 while s1 s2 return p main chars 20 printf s n strcpy s Welcometoyou 结构体与指针 指向结构体变量的指针 结构体指针变量的定义 struct结构体名 指针变量名 例如 structstudent pt structstudent intnum charname 20 charsex intage stu 使用结构体指针变量引用成员形式 结构体指针名 成员名 结构体指针名 成员名 结构体变量名 成员名 structstudent intnum charname 20 charsex intage stu structstudent p p num p num stu num p stu num 例 结构体指针的使用 include includestructstudent intnum charname 20 charsex intage main structstudentstu p p 例 结构体数组指针的使用 structstudent intnum charname 20 charsex intage stu 3 10101 LiLin M 18 10102 ZhangFun M 19 10103 WangMin F 20 main structstudent p for p stu pnum p name p sex p age 10101 LiLin M 18 10102 ZhangFun M 19 10103 WangMin F 20 结构体指针作函数参数 用结构体变量的成员作参数 单值传递用结构体变量作参数 多值传递用指向结构体变量或数组的指针作参数 地址传递 例9 17 采用 引用传递 的方式 用指向结构体的指针变量作参数 在input函数中输入并计算平均成绩 在main函数输出 defineN4 include defineFMT 5d 11s 5d 8d 8d 10 1f n structst intnum charname 11 ints 3 floataver voidinput structst p scanf d s d d d 指针与链表 链表可以动态的进行存储分配 head 头指针 存放一个地址 指向链表中的第一个元素 每一个元素称为一个 结点 每个结点都包括两部分 1 用户需要的实际数据 2 下一个结点的地址 表尾 它的地址部分放一个 NULL 链表到此结束 可用结构体类型的变量来存储链表中的结点元素 每一个结点中存放地址的部分可用指针来实现 例 structstudent intnum floatscore structstudent next 简单静态链表 defineNULL0structstudent longnum floatscore structstudent next main structstudenta b c head p a num 9901 a score 89 5 b num 9903 b score 90 c num 9905 c score 85 head 9901 89 5 9903 90 9905 85 a b c NULL a b c NULL 动态链表 处理动态链表所需的函数 1 malloc函数 void malloc unsignedintsize 作用是 在内存的动态存储区分配一个长度为size的连续空间 原型说明在 stdlib h 头文件和 alloc h 头文件中 2 calloc函数 void calloc unsignedn unsignedsize 作用是 在内存的动态区分配n个长度为size的连续空间 3 free函数 voidfree void p 作用是 释放由p指向的内存区 typedefstructNode intdata structNode next Node 链表的插入操作 s next pre next pre next s 顺序可以颠倒吗 voidInsList Node L inti inte Node pre s intk 0 pre L while pre NULL 链表的删除操作 pre next pre next next free r voidDelList Node L inti Node pre r pre L intk 0 while pre next NULL 建立动态链表
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 行政法学考前心理调备与调整:试题及答案
- 电气火灾应急预案内容(3篇)
- 高考数学基础知识点试题及答案
- 水电站火灾逃生应急预案(3篇)
- 自我成长的旅程2024年高考作文考试试题及答案
- 行政法学必背试题与答案清单
- 火灾应急预案培训报道(3篇)
- 火灾应急预案人员分工(3篇)
- 鹿泉小区火灾应急预案(3篇)
- 机器学习的伦理问题考核试题及答案
- 高校学生资助诚信教育主题活动
- 跨国公司海外人力资源外包与派遣管理合同
- LNG 加气站防雷安全培训与应急演练记录 202505
- 普惠金融专员试题及答案
- 【课件】认识民法典+课件统编版道德与法治七年级下册
- 2025年航天知识竞赛题库及答案
- 2025年人教版小学小升初科学模拟试卷(含答案解析)
- 《金属疲劳与断裂》课件
- 2025年《民法典》应知应会知识竞赛题库(含各题型)
- 灸法完整版本
- 剧场协议合同范例
评论
0/150
提交评论