《C语言的指针和结构体.ppt》由会员分享,可在线阅读,更多相关《C语言的指针和结构体.ppt(39页珍藏版)》请在三一办公上搜索。
1、C 语言中的指针与结构体,指针的概念,地址 内容 变量名,int x=20,y=1,z=155;int*p;p=,指针变量,指针变量:存放地址的变量,某个变量的地址,指向,(内存单元),指针变量所指向的变量的类型,int*p;p 是整型指针,指向整型变量float*fp;fp 是浮点型指针,指向浮点型变量char*cp;cp 是字符型指针,指向字符型变量,类型名*指针变量名,指针声明符,指针变量的定义,取地址运算(&)和间接访问运算(*),*:间接访问运算符,访问指针所指向的变量。*p:指针变量 p 所指向的变量。,*p,如果指针的值是某个变量的地址,通过指针就能间接访问那个变量。把 a 的地
2、址赋给 p,即 p 指向 a,/指针变量的类型和它所指向变量的类型相同,(1)当 p=指针p所指向的变量,即a,改变变量值(3)&*p 与&a 相同,是地址*&a 与 a 相同,是变量(4)(*p)+等价于 a+将 p 所指向的变量值加1*p+等价于*(p+)/先取*p,然后 p 自加,此时p不再指向a,说明,int a=3,*p;p=,赋值运算,*p1*p2,int a=3,*p1,*p2;p1=/p2 也指向 a,/相同类型的指针才能相互赋值,注意:指针变量必须初始化。,void main()int a=1,b=2,*p1,*p2,*pt;p1=,a=1;b=2;*p1=1,*p2=2a=
3、1;b=2;*p1=2,*p2=1,指针作为函数参数,void swap(int*px,int*py)int t;t=*px;*px=*py;*py=t;,要通过函数调用来改变主调函数中某个变量的值:(1)在主调函数中,将该变量的地址或者指向该变量的指针作为实参(2)在被调函数中,用指针类型形参接受该变量的地址(3)在被调函数中,改变形参所指向变量的值,/swap(,数组和地址间的关系,int a100,*p;数组名代表一个地址,它的值是数组首元素的地址(基地址)a+i 是距数组a的基地址的第i个偏移,sum=0;for(i=0;i 100;i+)sum=sum+ai;,*(a+i),下标运算
4、符 的含义,任何由数组下标来实现的操作都能用指针来完成int a100,*p;p=a;或p=,&ai aia+i*(a+i),p+i*(p+i)&pi pi,p=a;sum=0;for(i=0;i 100;i+)sum=sum+pi;,等价,等价,*(p+i),sum=0;for(p=a;p=,用指针实现内存动态分配,变量在使用前必须被定义且安排好存储空间存储空间分配分为两种:静态分配动态分配静态分配:全局变量、静态局部变量的存储是在编译时确定,在程序开始执行前完成。自动变量,在执行进入变量定义所在的语句时为它们分配存储,变量占用空间的大小也是静态确定的。,动态存储分配,不是由编译系统分配的,
5、而是由用户在程序中通过动态分配获取。使用动态内存分配能有效地使用内存使用时申请用完就释放,动态内存分配的步骤,(1)了解需要多少内存空间。(2)利用C语言提供的动态分配函数来分配所需要的存储空间。(3)使指针指向获得的内存空间,以便用指针在该空间内实施运算或操作。(4)当使用完毕内存后,释放这一空间。,动态存储分配函数malloc(),void*malloc(unsigned size)在内存的动态存储区中分配一连续空间,其长度为size若申请成功,则返回一个指向所分配内存空间的起始地址的指针若申请内存空间不成功,则返回NULL返回值类型:(void*)通用指针的一个重要用途将malloc的返
6、回值转换到特定指针类型,赋给一个指针,malloc()示例,/*动态分配n个整数类型大小的空间*/if(p=(int*)malloc(n*sizeof(int)=NULL)printf(“Not able to allocate memory.n”);exit(1);调用malloc时,用 sizeof 计算存储块大小每次动态分配都要检查是否成功,考虑例外情况处理 虽然存储块是动态分配的,但它的大小在分配后也是确定的,不要越界使用。,动态存储释放函数free(),void free(void*ptr)释放由动态存储分配函数申请到的整块内存空间,ptr为指向要释放空间的首地址。当某个动态分配的存
7、储块不再用时,要及时将它释放,分配调整函数realloc(),void*realloc(void*ptr,unsigned size)更改以前的存储分配ptr必须是以前通过动态存储分配得到的指针参数size为现在需要的空间大小如果调整失败,返回NULL,同时原来ptr指向存储块的内容不变。如果调整成功,返回一片能存放大小为size的区块,并保证该块的内容与原块的一致。如果size小于原块的大小,则内容为原块前size范围内的数据;如果新块更大,则原有数据存在新块的前一部分。如果分配成功,原存储块的内容就可能改变了,因此不允许再通过ptr去使用它。,结构体,结构体的定义,结构体类型定义的一般形式
8、为:struct 结构名 类型名 结构成员名1;类型名 结构成员名2;类型名 结构成员名n;;,/关键字struct和它后面的结构名一起组成一个新的数据类型名,结构体的嵌套定义,struct address char city10;char street20;int code;char zip6;,struct list char name10;int sex;int age;struct address addr;char telephone13;char email30;list;,在定义嵌套的结构体类型时,必须先定义成员的结构体类型,再定义主结构体类型。,结构体变量的定义和初始化,三种定
9、义结构变量的方式:1.单独定义先定义结构体类型,再定义具有这种结构体类型的变量 struct list char name10;/*姓名*/int age;/*年龄*/char telephone13;/*联系电话*/;struct list friend1,friend2;,2.混合定义在定义结构体类型的同时定义结构体变量 struct listchar name10;int age;char telephone13;friend1,friend2;3.无类型名定义在定义结构体变量时省略结构体名struct char name10;int age;char telephone13;frien
10、d1,friend2;,结构体变量的初始化,struct list friend1=Zhang,26,;,name age telephone,结构体变量成员的使用,结构体变量名.成员名friend1.age=26;strcpy(friend1.name,Zhang San);strcpy(friend1.addr.zip,210044);,struct list char name10;int age;char telephone13;friends10;结构数组friends,它有10个数组元素,从friends0到friends9,每个数组元素都是结构体类型struct list变量。,
11、结构体数组,结构体数组的初始化,struct friends_list friends10=zhang san,26,;,结构体数组元素,结构数组元素的成员引用结构体数组名下标.结构体成员名 使用方法与同类型的变量完全相同friends5.age=26;strcpy(friends5.name,Zhang San);friends4=friends1;,结构体指针,结构体指针:指向结构类型变量的指针结构体类型 struct liststruct list friend1=zhang,26,;struct friends_list*p;p=,结构体指针的使用,(1)用*p访问结构成员(*p).a
12、ge=26;(2)用指向运算符“-”访问指针指向的结构成员。p-age=26;当p=,结构体指针作为函数参数,当结构指针作为函数的参数时,执行效率高,可以完成比基本类型指针更为复杂的操作。例:输入10个学生的学号、姓名和成绩,输出学生的成绩等级和不及格人数。每个学生的记录包括学号、姓名、成绩和等级要求定义和调用函数set_grade根据学生成绩设置等级,并统计不及格人数等级设置:A:85100;B:7084;C:6069;D:059,源程序,#define N 10struct student int num;char name20;int score;char grade;int main(
13、void)int count;struct student stuN,*ptr;ptr=stu;/*输入 略*/count=set_grade(ptr);,int set_grade(struct student*p)int i,n=0;for(i=0;i score=85)p-grade=A;else if(p-score=70)p-grade=B;else if(p-score=60)p-grade=C;else p-grade=D;n+;return n;,调用set_grade返回主函数后,主函数中结构体数组stu的元素的grade成员已经被赋值.,与结构体变量作为函数参数相比,用结构
14、体指针作为函数参数的效率更高,因而是更好的选择。,多文件结构,工作区,工程1,工程2,工程n,头文件,源文件,例:VC中的多文件结构,示例,#include#include#include#include/常量定义#define LIST_INIT_SIZE 100#define LISTINCREMENT 10#define OK 1#define ERROR 0#define OVERFLOW-2#define True 1#define False 0/函数返回值类型定义typedef int Status;/表节点数据类型定义typedef int ElemType;,/顺序表类型定义
15、typedef structElemType*elem;int length;int listsize;SqList;/顺序表各操作声明Status InitList_Sq(SqList,头文件:SqList.h,#include SqList.h/各操作的实现Status InitList_Sq(SqList,源文件:SqList.cpp,int ListEmpty_Sq(SqList L)return(L.length=0);int ListLength_Sq(SqList L)return L.length;Status GetElem_Sq(SqList L,int i,ElemTyp
16、e,Status ListInsert_Sq(SqList,Status ListDelete_Sq(SqList,#include SqList.hvoid main()SqList L;int i,num;cout创建顺序表endl;if(!InitList_Sq(L)cout表创建失败;/创建空顺序表Lelse/产生各节点srand(time(NULL);for(i=0;i10;i+)/产生10个整数,插入顺序表表尾 num=rand()%100;ListInsert_Sq(L,i+1,(ElemType)num);,源文件:SqDemo.cpp(包含主函数main(),/输出原始顺序表的各个值cout生成的原始表为:;PrintList_Sq(L);/输出第2个节点的数据值GetElem_Sq(L,2,num);coutendl第2个元素值为:numendl;/删除第2个节点ListDelete_Sq(L,2,num);/输出修改后的顺序表的各个值cout修改后的表为:;PrintList_Sq(L);coutendl;,