C语言程序设计 -课件 第8、9章 指针的应用、结构体和共用体_第1页
C语言程序设计 -课件 第8、9章 指针的应用、结构体和共用体_第2页
C语言程序设计 -课件 第8、9章 指针的应用、结构体和共用体_第3页
C语言程序设计 -课件 第8、9章 指针的应用、结构体和共用体_第4页
C语言程序设计 -课件 第8、9章 指针的应用、结构体和共用体_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

魅力指挥棒—指针的应用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; for(;p<a[0]+L;p++)//从键盘上输入L个数据scanf("%d",p);for(i=0;i<M;i++){p=a[i];//取第i行的首地址 for(;p<a[i]+N;p++)//输出第i行的n个元素 printf("%5d",*p);printf("\n");//换行} }

例8-4用指针输出二维数组的各元素。8.4趣味实例—排队入座综合运用指针与数组知识趣味实例实训目的1.熟练掌握指针的语法格式,理解各种指针类型。2.掌握指针在简单变量、数组中的应用,并灵活针对实际问题编程。实训内容1.用指针方法编程实现3个整数的大小排序。2.按指定要求对已排序的数列进行重新排列。要求编程实现从数列的指定位置开始的n个数按逆序重新排列,并输出新数列。知识准备设计算法编程训练1)实例一:分析-流程图-编写程序。2)上机验证调试。3)实例二:分析-流程图-编写程序。4)上机验证调试。编程提示实例一:固定预设大小顺序,然后相互比较,不符合预设的交换位置即可。实例二:指定位置开始n个数逆序重排形成新数列并输出。因位置不固定,逆序的个数不确定,所以编程处理时采用指针,可以灵活实现对数列的指向操作。实训流程本章小结:组合的力量—结构体和共用体C语言程序设计第九章本章目录01.认识结构体02.结构体变量的初始化与引用03.共用体及共用体的使用04.趣味实例9.1

认识结构体定义复杂的自定义数据类型结构体类型的定义一般形式struct 结构体类型名称{

数据类型

成员名1;数据类型

成员名2;…数据类型

成员名n;};说明“struct”是定义结构体类型的关键字,其后是所定义的结构体类型名称,在结构体类型名称下的花括号中,定义了结构体类型的成员项,每个成员由“数据类型”和“成员名”共同组成。示例structStudent{intnum;charname[10];charsex;intage;charaddress[30];};结构体类型的定义1)结构体类型定义以关键字struct开头,其后为结构体类型的名称,该名称的命名规则与变量的命名规则相同。2)定义好一个结构体类型后,并不意味着立即分配一块内存单元来存放各个数据成员,它只是向编译器声明,该结构体类型由哪些数据类型的成员构成,各占多少个字节,按什么格式存储,并把它们当作一个整体来处理。3)结构体类型定义末尾括号后的分号不可缺少。小贴士结构体变量的定义先定义结构体类型,再定义结构体变量structStudent{intnum;

charname[10];

charsex;

intage;

charaddress[30];};structStudentboy1,boy2;在定义结构体类型的同时定义结构体变量structStudent{intnum;

charname[10];

charsex;

intage;

charaddress[30];}boy1,boy2;直接定义结构体变量struct{intnum;

charname[10];

charsex;

intage;

charaddress[30];}boy1,boy2;实例体验:structdate{intmonth;intday;intyear;};struct{intnum;charname[20];charsex;structdatebirthday;floatscore;}stu1,stu2;例9-1

结构体类型的定义及变量声明。9.2结构体变量的初始化与引用操作结构体中的数据结构体变量的初始化定义结构体类型和变量的同时,对结构体变量初始化在声明结构体变量的同时,可以直接指定每个成员的初始值。按成员定义顺序赋值。未初始化的成员会被自动赋默认值(如0)。示例:structStudent{charname[50];intage;floatscore;}stu1={"JohnDoe",20,85.5};先声明结构体类型,之后定义结构体变量并对其初始化示例:structStudent{charname[50];

intage;

floatscore;};structStudentstu1={"JohnDoe",20,85.5};结构体变量的引用书写格式例如:#include<stdio.h>

structStudent

{charname[50];

intage;

floatscore;

};

structStudentstudent1={"Alice",20,90.5};

main()

{printf("Name:%s\n",);//访问结构体成员

printf("Age:%d\n",student1.age);

printf("Score:%.2f\n",student1.score);}结构体变量名.成员名实例体验:structdate{intmm,dd,yy;};main(){structdated1,d2;d1.mm=9;d1.dd=1;d1.yy=2004;d2=d1;printf("%d-%d-%d\n",d2.mm,d2.dd,d2.yy);}例9-2定义两个同属于类型structdate的变量d1和d2,先对变量d1赋值,再将d1赋给变量d2。实例体验:#include<stdio.h>structstu{charname[30];floatscore[3];}stu1;main(){printf("请输入学生姓名及三门课的成绩:\n");scanf("%s%f%f%f",,&stu1.score[0],&stu1.score[1],&stu1.score[2]);printf("学生:%s的三门课成绩分别为:",);printf("%.2f,%.2f,%.2f\n",stu1.score[0],stu1.score[1],stu1.score[2]);}例9-3输入学生成绩,并显示。9.3共用体及共用体的使用理解数据的共享存储共用体的概念共用体的概念为了节约内存或便于对数据进行处理,C语言允许不同类型的数据共享一段存储单元,这种共享存储单元的特殊数据类型被称为共用体类型,也可称之为联合类型。核心特性与机制互斥存储:同一时刻只能存储一个成员的值。

赋值覆盖:对某一成员赋值会覆盖其他成员,使其无效。

节省内存:复用同一块内存空间,高效利用资源。典型与结构体的区别结构体:各成员拥有独立空间,总大小是成员之和,成员“共存”。

共用体:所有成员共享同一块内存,大小等于最大成员,成员“互斥”。共用体类型的定义和变量定义共用体类型的定义共用体变量的定义书写格式:union共用体名{

数据类型

成员名1;

数据类型

成员名2;…

数据类型

成员名n;};1.先定义共用体类型,再定义共用体变量uniondata{intm;

floatx;

charc;};uniondataa,b;2.定义共用体类型的同时定义共用体变量

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论