版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
魅力指挥棒—指针的应用C语言程序设计第八章本章目录01.认识指针02.指针变量的定义及引用03.指针与数组04.趣味实例8.1认识指针理解内存地址与指针的概念指针概念及作用
当在程序中定义了一个变量,对程序进行编译时,系统就会给这个变量分配内存单元。编译系统根据程序中定义的变量类型,分配一定长度的空间。内存区的每一个字节有一个编号,这就是“地址”。由于通过地址能找到所需的变量单元,因此唯一标识变量储存位置的地址,通常称为“指针”。C语言中的地址包括位置信息(内存编号,或称纯地址)
和它所指向的数据的类型信息,或者说它是“带类型的地址”。存储单元的地址和存储单元的内容是两个不同的概念。例如:inti=1,j=2,k=3;//设int变量占2字节指针变量指针变量
用一个变量来存放内存的地址,这个变量就称为指针变量,指针类型丰富多样,但不同类型指针变量所占用的存储单元长度是相同的。在程序中一般是通过变量名来引用变量的值。直接按变量名进行的访问,称为“直接访问”方式。还有一种“间接访问”的方式,即将变量的地址存放在另一变量(指针变量)中,然后通过该指针变量来找到对应变量的地址,从而访问变量。
严格地说,一个指针是一个地址,是一个常量。而一个指针变量却可以被赋予不同的指针值,是变量。但常把指针变量简称为指针。为了避免混淆,我们约定:“指针”是指地址,是常量,“指针变量”是指取值为地址的变量。定义指针的目的是为了通过指针去访问内存单元。例如:将变量x的地址2060存放到另一个变量p中,即p的值为2060,这样通过变量p可以找到变量x的地址,从而找到x的值。存放地址的变量p就是指针变量。可以形象地说,p指向x,变量x与指针变量p的关系如图8-2所示。
8.2指针变量的定义及引用掌握指针变量的基本操作指针变量的定义定义格式类型标识符*指针变量名;例如:int*pointer_1,*pointer_2;//定义了两个int类型的指针变量类型标识符决定指针指向的数据类型,必须与目标变量类型严格一致。星号*指针运算法,表示其后的变量是指针变量,不能省略。指针变量名遵循C语言标识符命名规则,用于存储内存地址。结构说明1)定义指针变量时必须指定其类型。一个变量的指针的含义包括两个方面,一是以存储单元编号表示的纯地址,二是它指向的存储单元的数据类型。2)如何表示指针类型。指向整型数据的指针类型表示为“int*”,读作“指向int类型的指针”或简称“int指针”。3)指针不能指向常量,例如“int*p;p=&50;”是错误的。4)指针的内容不能直接输入,例如“intp;scanf("%d",&p);”是错误的,“int*p,a;p=&a;scanf("%d",p);”是正确的,此处是输入变量a的值。定义指针变量要注意:指针变量的定义示例指针类型指针定义语句里的指针名字去掉,剩下的部分就是这个指针的类型。指针所指向的类型通过指针来访问指针所指向的内存区域时,指针所指向的类型决定了编译器将把那片内存区里的内容当作什么类型来看待。int*ptr;//指针的类型是int*char*ptr;//指针的类型是char*int**ptr;//指针的类型是int**int(*ptr)[3];//指针的类型是int(*)[3]示例int*ptr;//指针所指向的类型是intchar*ptr;//指针所指向的类型是charint**ptr;//指针所指向的类型是int*int(*ptr)[3];//指针所指向的类型是int()[3]指针的引用
在指针的引用中涉及两个运算符"*"和"&","*"是指针运算符,或称为“间接访问”运算符,如*p1表示指针变量p1所指向的变量;"&"称为取地址运算符,如为了让指针p指向变量x,可执行p=&x,此时变量x的地址即存入了指针p中。若要改变x变量的值,也可通过改变*p的值来实现,如执行“*p=47;”,则此时x=47。
指针变量既可以在定义时初始化,也可以在定义后赋初值,不能未赋值就引用指针存取值。指针变量可以如同一般变量一样进行赋值、加减计算。指针的引用取地址运算符`&`作用:获取变量的内存地址格式:&变量名示例:p=&a;(将变量a的地址赋值给指针p)解引用运算符`*`作用:访问指针指向的内存值格式:*指针变量名示例:printf("%d",*p);(输出p指向的值)*p=20;(修改p指向的变量值)指针变量的初始化野指针的危害未初始化的指针值随机,指向内存任意位置。直接使用(如*p=10)可能导致程序崩溃或数据被意外篡改。(补充内容)指针的初始化定义时直接赋值:
inta,*p=&a;先定义后赋值:
inta,*p;p=&a;空指针
NULLNULL通常定义为0,表示指针无效。良好习惯:int*p=NULL;注意:NULL指针不可解引用(*p)。(补充内容)指针的引用说明指针变量中只能用于存储变量的地址,不可将一个整型常量赋给一个指针变量。实例体验例8-1通过指针变量访问变量。#include<stdio.h>main(){inta=7,b=5,c,*pa=&a,*pb;pb=&b;c=*pa+*pb;printf("a=%d,*pa=%d\n",a,*pa);printf("b=%d,*pb=%d\n",b,*pb);printf("%d+%d=%d\n",a,b,c);printf("%d+%d=%d",*pa,*pb,c);}#include<stdio.h>main(){int*p,*pa,*pb,a,b;printf("请输入两个整数:");scanf("%d,%d",&a,&b);pa=&a;pb=&b;if(a<b){p=pa;pa=pb;pb=p;}printf("a=%d,b=%d\n",a,b);printf("从大到小输出两个整数:%d,%d\n",*pa,*pb);}例8-2输入a和b两个整数,按先大后小的顺序输出a和b两个整数,使用指针编写程序。8.3指针与数组利用指针高效操作数组指针与一维数组
数组一旦被定义,其元素将在内存中占用一段连续的存储单元,每个数组元素都占用一个存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个指针变量中)。所谓数组指针,是指数组的起始地址,数组元素的指针就是数组元素的地址。可以用一个指针变量指向一个数组元素。
数组名代表数组的首地址。比如“int[5]={12,34,56,78,90};”首地址是数组的第1个元素的地址,所以该数组的数据在内存中的存储结构如图
所示。。指针与一维数组指针与一维数组建立关联将数组的首地址放入指针中,就让指针变量指向数组,如:inta[5],*p=a;//指针变量p指向数组a。一维数组的引用——引用各个数组元素的地址
1)通过使用数组名引用。如“inta[6]”2)通过指针引用。如“inta[6],*p=a;p++;”注意:此处数组名a是常量,不能进行自增/自减运算。指针与一维数组一维数组的引用——引用各个数组元素所在的存储单元或存储单元里的值
1)通过对数组名、指针变量的取内容运算符*。上图
中数组的运算:*p=a[0],*(p+1)=a[1],a=a[0],*(a+1)=a[1],依次类推。2)通过指针变量后面跟下标。数组和指针建立关联后,可以把指针带入数组名引用各个数组元素,即p[i]与a[i]代表值相同。小贴士:1)指针变量指向数组元素a[i]的方法是p=&a[i]或p=a+i。2)与数组名的区别,指针变量是一个变量,其值可以改变,数组名是数组的首地址,是地址常量,其值不能变化。例如,若定义“inta[10],*p=a;”,则a++是错误的,p++是允许的。3)未初始化的指针指向不确定的值。4)若有定义“inta[10],*p=a,i;”,则a[i]、*(a+i)、*(p+i)等价。5)注意指针的动态性,a[i]与*(p+i)不总是相等的,例如:inta[10],*p,i=5;p=a+1;上述例子中*(p+i)等价于a[6]。指针与二维数组二维数组定义二维数组定义时的行数和列数分别用两个方括号分开,把二维数组看作是一种特殊的一维数组。指针与二维数组建立关联二维数组的引用:同一维数组。小贴士:设“inta[4][5],*p=a[0],i,j;”。1)a是该二维数组的首地址,即元素a[0][0]的首地址。a+i是行指针,等同于a[i],是第i+1行的首地址,即&a[i][0]。2)a+1与p+1不同,a+1以二维数组的“行长度”为增量,而p+1则以二维数组的“元素长度”为增量,即a+1加1行的增量,p+1加一个元素的增量。3)a[i]+j是a[i][j]的地址,等价于a[i][j]。4)*(a+i)与*a[i]不同,*a[i]表示元素a[i][0]的值,而*(a+i)表示元素a[i][0]的地址。5)表示元素a[i][j]的方法有*(a[i]+j)、*(*(a+i)+j。先定义指针、二维数组,然后将二维数组首地址赋值给指针变量,例如“inta[4][3];int*p;p=a[0];”。通过指针遍历一维数组核心代码实现#include<stdio.h>intmain(){intarr[]={1,2,3,4,5};intp,n=sizeof(arr)/sizeof(arr[0]);//方法一:指针移动遍历(推荐)for(p=arr;p<arr+n;p++){printf("%d",*p);}//方法二:指针下标形式p=arr;for(inti=0;i<n;i++){printf("%d",p[i]);}return0;}方法一:指针移动遍历原理:指针p从数组首地址arr开始,每次执行p++指向下一个元素,直到p指向arr
+n。优势:直接操作内存地址,避免了数组下标运算,执行效率更高。方法二:指针下标形式原理:利用p[i]语法访问元素,其本质等价于*(p+i),依然是地址运算。场景:在需要保留数组下标语义的场景下,这种写法比直接的指针运算更易读。指针数组与数组指针指针数组本质:是数组,元素是指针变量。定义:基类型*数组名[长度];(优先级:[]>*)用途:存放多个字符串首地址。示例:char*strs[]={"a","b","c"};数组指针本质:是指针,指向一个一维数组。定义:基类型(*指针名)[长度];(括号提升*优先级)用途:指向二维数组的某一行。示例:int(*p)[4];(p指向含4个int的数组)实例体验例8-3用三种方法输出数组元素。#include<stdio.h>main(){staticinta[5]={5,4,3,2,1};inti,*p=a;for(i=0;i<5;i++)printf("%d,%d,%d\n",a[i],*(a+i),*(p+i));}#include<stdio.h>#defineM4#defineN3#defineLM*Nmain(){inta[M][N],*p=a[0],i;
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 串联电路的电压的分配
- 图解植物栽植的科学布局正式版
- 可编程序控制器应用第三章
- 人力资源管理新概念
- 井下作业施工前准备与验收
- 课时1 辩证分合与质量互变
- 2026 年秋分节气感受丰收喜悦传承中华传统美德课件
- 2026年秋季小学生拒绝垃圾食品健康引导课件
- 耐火保温材料购销合同 工业窑炉耐火保温棉材料采购协议
- 2026年自然教育讲解员(自然教育讲解)试题及答案
- 2026秋改版人教版三年级上册道德与法治全册教案
- 摩托车交通安全管理现状与规范培训
- 数据库应用与数据分析MySQL(第2版) 课件全套 项目1-8 数据库概述-MySQL数据处理与数据分析
- 2026年秋季开学传染病防控安全知识宣讲课件
- 2026年新疆高考物理真题试卷及参考答案
- 2026秋新教材人教版小学数学五年级上册教学计划及进度表
- 2026年重庆市中考数学真题试卷(真题+答案)
- 2026-2027学年第一学期高中物理学校工作计划
- 2026年北师大八下数学期末模拟卷(四川成都专用八下全册)
- 2026非洲食品冷链物流行业市场现状分析及冷链技术与食品安全保障研究报告
- 2026年绵阳市涪城区社区工作者招聘考试真题(附答案)
评论
0/150
提交评论