1、信息科学与工程学院C语言程序设计语言程序设计信息科学与工程学院第第7章章 指针指针 本章需要掌握的知识点本章需要掌握的知识点指针的概念指针的概念指针的运算指针的运算指针作为函数的参数时的运作方式指针作为函数的参数时的运作方式指针跟数组的关系指针跟数组的关系动态内存申请和释放动态内存申请和释放信息科学与工程学院内容安排内容安排 7.1 指针的基本概念和运算指针的基本概念和运算 7.2 指针与函数指针与函数 7.3 指针与一维数组(包含内存的动态分配)指针与一维数组(包含内存的动态分配) *7.4 二级指针二级指针 *7.5 指针数组指针数组 *7.6 指针与二维数组指针与二维数组 *7.7 命令
2、行参数命令行参数信息科学与工程学院7.1 指针的基本概念和运算指针的基本概念和运算地址和指针概念地址和指针概念.ppt.ppt信息科学与工程学院指针的概念指针的概念指针是什么?地址是什么?指针是什么?地址是什么?如何定义和使用指针?如何定义和使用指针?为什么需要指针?为什么需要指针?信息科学与工程学院程序中程序中: : int i; float k; 内存中每个字节有一个编号内存中每个字节有一个编号-地址地址.2000200120022005内存内存02003ik 函数调用时为其分配内存单元函数调用时为其分配内存单元变量变量是对程序中数据是对程序中数据存储空间的抽象存储空间的抽象地址和指针的概
3、念地址和指针的概念信息科学与工程学院.2000200420062005整型变量整型变量i10变量i_pointer200120022003 指针与指针变量指针与指针变量指针:代表内存的某个地址,指向某个变量单元。指针:代表内存的某个地址,指向某个变量单元。指针变量:专门存放内存地址的变量叫指针变量指针变量:专门存放内存地址的变量叫指针变量2000指针指针变量 变量的变量的内容内容 变量的变量的地址地址指针变量指针变量变量变量变量地址变量地址(指针指针)变量值变量值指向地址存入地址存入指针变量指针变量信息科学与工程学院为什么需要指针为什么需要指针方便数组和字符串的处理方便数组和字符串的处理在调用
4、函数时可以得到多个返回结果。在调用函数时可以得到多个返回结果。动态链表建立的需要动态链表建立的需要接口控制的需要接口控制的需要信息科学与工程学院指针变量的定义和使用指针变量的定义和使用指针变量定义的形式:指针变量定义的形式: 类型名类型名 *指针变量名指针变量名;取变量的地址的形式:取变量的地址的形式: &变量名变量名引用变量的值方式:引用变量的值方式:直接用变量名为直接引用;直接用变量名为直接引用;通过指针变量加上通过指针变量加上*号为间接引用号为间接引用;1001000ap1000信息科学与工程学院.2000200420062005整型变量整型变量i10变量变量i_pointer20012
5、00220032000指针变量指针变量200010i_pointer*i_pointer&i_pointerii_pointer &i &(*i_pointer)i *i_pointer *(&i)信息科学与工程学院直接访问:按变量名存取变量值直接访问:按变量名存取变量值间接访问:通过变量地址去访问变量值间接访问:通过变量地址去访问变量值例例 i=3; -直接访问直接访问指针变量指针变量.2000200420062005整型变量整型变量i10变量变量i_pointer20012002200320003例例 *i_pointer=20; -间接访问间接访问20信息科学与工程学院注意事项注意事项如
6、果有了定义如果有了定义int *p,说明,说明p本身也是一个变量,本身也是一个变量,也有地址。也有地址。指针变量是有类型的。指针变量是有类型的。int i; float *p; p=&i; /*错误错误 */ “*”号在定义指针和运算时所起的作用是不同的。号在定义指针和运算时所起的作用是不同的。信息科学与工程学院 7.2 指针与函数指针与函数注意:注意:动态内存分配内容放置在动态内存分配内容放置在7.3进行讲解。进行讲解。在函数调用时,实参向形参传递的方式是什在函数调用时,实参向形参传递的方式是什么?么? 单向赋值单向赋值函数调用(函数调用(COPY)ppt函数调用(指针)函数调用(指针) p
7、pt信息科学与工程学院void swap(int x,int y) int temp; temp=x; x=y; y=temp;void main() int a,b; scanf(%d,%d,&a,&b); if(ab) swap(a,b); printf(n%d,%dn,a,b);例例 将数从大到小输出将数从大到小输出.20002008200A2002200420065变量a 变量b(main)9 变量temp 变量y 变量x(swap)559 59COPY实参到形参是赋值传递实参到形参是赋值传递信息科学与工程学院void swap(int x,int y) int temp; temp=
8、x; x=y; y=temp;void main() int a,b; scanf(%d,%d,&a,&b); if(ab) swap(a,b); printf(n%d,%dn,a,b);例例 将数从大到小输出将数从大到小输出.20002008200A2002200420065变量a 变量b(main)9运行结果:运行结果:5,9信息科学与工程学院void swap(int *p1, int *p2) int p; p=*p1; *p1=*p2; *p2=p;void main() int a,b; int *pointer_1,*pointer_2; scanf(%d,%d,&a,&b);
9、pointer_1=&a; pointer_2=&b; if(ab)swap(pointer_1,pointer_2); printf(n%d,%dn,a,b);.20002008200A200220042006200C200E2010.59整型变量整型变量a 整型变量整型变量b(main)指针指针pointer_1指针指针pointer_220002002(swap)指针指针p1指针指针p2整型整型p5920002002COPY5指针变量作为函数参数。特点:指针变量作为函数参数。特点:地址传递,地址传递,共享内存共享内存,“双向双向”传递传递信息科学与工程学院void swap(int *p
10、1, int *p2) int p; p=*p1; *p1=*p2; *p2=p;void main() int a,b; int *pointer_1,*pointer_2; scanf(%d,%d,&a,&b); pointer_1=&a; pointer_2=&b; if(ab)swap(pointer_1,pointer_2); printf(n%d,%dn,a,b);.20002008200A200220042006200C200E2010.59整型变量整型变量a 整型变量整型变量b(main)指针指针pointer_1指针指针pointer_22000200259地址传递地址传递运
11、行结果:运行结果:9,5信息科学与工程学院注意事项注意事项无论形参的类型是什么,在函数调用时,无论形参的类型是什么,在函数调用时,实参都是单向的将值赋给形参。实参都是单向的将值赋给形参。为什么为什么scanf函数中的参数是地址的列表而函数中的参数是地址的列表而不是变量的列表?不是变量的列表? scanf(“%d%d”, &a, &b);如果想在被调函数中改变调用函数中变量如果想在被调函数中改变调用函数中变量的值,如何做?的值,如何做?信息科学与工程学院*返回指针值的函数、指向函数的指针返回指针值的函数、指向函数的指针(自学)(自学)信息科学与工程学院7.3 指针与一维数组及指针与一维数组及 指
12、针的运算指针的运算一个变量有地址,那么每个数组元素是否有一个变量有地址,那么每个数组元素是否有地址?地址?属于同一个数组的元素在内存中是放置在一属于同一个数组的元素在内存中是放置在一起的,占用一片连续的内存,那么整个数组起的,占用一片连续的内存,那么整个数组的地址应该如何表示比较合适?的地址应该如何表示比较合适?既然数组元素是放置在一起的,我们是否可既然数组元素是放置在一起的,我们是否可以通过指针的移动来访问数组中不同的元素?以通过指针的移动来访问数组中不同的元素?如果指针可以移动,那么应该怎样移动?如果指针可以移动,那么应该怎样移动?信息科学与工程学院如果指针如果指针p指向数组指向数组a的第
13、一个元素,那么的第一个元素,那么如何引用数组第一个元素的值?如何引用数组第一个元素的值?如何引用数组第二个元素的值?如何引用数组第二个元素的值?数组的名字代表数组的首地址,该地址值数组的名字代表数组的首地址,该地址值不能发生改变,即数组名是一个常量指针。不能发生改变,即数组名是一个常量指针。数组与指针数组与指针ppt(一维)(一维)信息科学与工程学院指针变量的赋值运算指针变量的赋值运算p=&a; (将变量将变量a地址地址p)p=array; (将数组将数组array首地址首地址p)p=&arrayi; (将数组元素地址将数组元素地址p)p1=p2; (指针变量指针变量p2值值p1)指针的运算指
14、针的运算信息科学与工程学院指针的算术运算:指针的算术运算:v指针可以加减一个整数,意义?指针可以加减一个整数,意义?p1p1与与p2p2指向同一数组,指向同一数组,p1- p2 p1- p2 代表代表两指针间元素个数两指针间元素个数p1+p2 p1+p2 无意义无意义例例 p指向指向int型数组,且型数组,且p=&a0; 则则p+1 指向指向a1例例 int a10;int a10; int int * *p=&a2;p=&a2; p+; p+; * *p=1;p=1;例例 int a10;int a10; int int * *p1=&a2;p1=&a2; int int * *p2=&a5
15、;p2=&a5; 则:则:p2-p1p2-p1?a0a1a2a3a4a5a6a7a8a9a数组数组pp+1,a+1p+i,a+ip+9,a+91信息科学与工程学院指针变量的关系运算指针变量的关系运算若若p1和和p2指向同一数组,则指向同一数组,则lp1p2 表示表示p1指的元素在后指的元素在后lp1= =p2 表示表示p1与与p2指向同一元素指向同一元素若若p1与与p2不指向同一数组,比较无意义不指向同一数组,比较无意义p= =NULL或或p!=NULL信息科学与工程学院 数组元素表示方法数组元素表示方法a0a1a2a3a9.aa+9a+1a+2地址元素下标法a0a1a2a9a0a1a2a3a
16、9.pp+9p+1p+2地址元素指针法*p*(p+1)*(p+2)*(p+9) 变址运算符ai *(a+i)ai pi *(p+i) *(a+i)*a*(a+1)*(a+2)*(a+9)p0p1p2p9信息科学与工程学院数组元素的引用方法数组元素的引用方法#include stdio.hvoid main() int a5,*pa,i; for(i=0;i5;i+) ai=i+1; pa=a; for(i=0;i5;i+) printf(*(pa+%d):%dn,i,*(pa+i); for(i=0;i5;i+) printf(*(a+%d):%dn,i,*(a+i); for(i=0;i5;
17、i+) printf(pa%d:%dn,i,pai); for(i=0;i5;i+) printf(a%d:%dn,i,ai);信息科学与工程学院例例 int a=1,2,3,4,5,6,7,8,9,10,*p=a,i=2; 数组元素地址的正确表示:数组元素地址的正确表示:(A)&(a+1) (B)a+ (C)&p (D)&pi数组名是数组名是地址常量地址常量p+,p- ( )a+,a- ( )a+1, *(a+2) ( )信息科学与工程学院#include stdio.hvoid main() int i,*p,a7; p=a; for(i=0;i7;i+) scanf(%d,p+); pr
18、intf(n); for(i=0;i7;i+,p+) printf(%d ,*p);例例 注意指针的当前值注意指针的当前值p=a;/指针归位指针归位pp58762730123456apppppp信息科学与工程学院 形参中数组类型的说明自动会转变为指针形参中数组类型的说明自动会转变为指针的说明的说明 数组名作函数参数,是数组名作函数参数,是地址传递地址传递用数组名作函数参数用数组名作函数参数信息科学与工程学院例例 将数组将数组a中的中的n个整数按相反顺序存放个整数按相反顺序存放 ij 3 7 9 11 0 6 7 5 4 20 1 2 3 4 5 6 7 8 9ijijijji117605947
19、23void inv(int x, int n) int t,i,j,m=(n-1)/2; for(i=0;i=m;i+) j=n-1-i; t=xi; xi=xj; xj=t; void main() int i,a10=3,7,9,11,0,6,7,5,4,2; inv(a,10); printf(The reverted array:n); for(i=0;i10;i+) printf(%d,ai); printf(n);m=4实参与形参均用实参与形参均用数组数组信息科学与工程学院void inv(int *x, int n) int t,*p,*i,*j,m=(n-1)/2; i=x;
20、 j=x+n-1; p=x+m; for(;i=p;i+,j-) t=*i; *i=*j; *j=t; void main() int i,a10=3,7,9,11,0,6,7,5,4,2; inv(a,10); printf(The reverted array:n); for(i=0;i10;i+) printf(%d,ai); printf(n); 实参用数组实参用数组,形参用指针变量形参用指针变量37911067542a0a1a2a3a4a5a6a7a8a9xp=x+ma数组60711594723ijijijjiji例例 将数组将数组a中的中的n个整数按相反顺序存放个整数按相反顺序存放
21、 信息科学与工程学院void inv(int *x, int n) int t,*i,*j,*p,m=(n-1)/2; i=x; j=x+n-1; p=x+m; for(;i=p;i+,j-) t=*i; *i=*j; *j=t; void main() int i,a10,*p=a; for(i=0;i10;i+,p+) scanf(%d,p); p=a; inv(p,10); printf(The reverted array:n); for(p=a;pa+10;p+) printf(“%d,*p); 实参与形参均用实参与形参均用指针变量指针变量例例 将数组将数组a中的中的n个整数按相反顺
22、序存放个整数按相反顺序存放 信息科学与工程学院void inv(int x, int n) int t,i,j,m=(n-1)/2; for(i=0;i=m;i+) j=n-1-i; t=xi; xi=xj; xj=t; void main() int i,a10,*p=a; for(i=0;i10;i+,p+) scanf(%d,p); p=a; inv(p,10); printf(The reverted array:n); for(p=a;pa+10;p+) printf(“%d,*p); 实参用指针实参用指针变量变量,形参用数组形参用数组例例 将数组将数组a中的中的n个整数按相反顺序存
23、放个整数按相反顺序存放 信息科学与工程学院指针与字符串指针与字符串字符串是如何放置在字符数组中的?字符串是如何放置在字符数组中的?数组与指针数组与指针(字符串字符串).ppt信息科学与工程学院例例 void main( ) char string=I love China!; printf(%sn,string); printf(%sn,string+7); IloveChistring0string1string2string3string4string5string6string7string8string9stringstring10string11string12string13n!a
24、0用字符数组存放一个字符串用字符数组存放一个字符串程序的运行结果是:程序的运行结果是:I love China!China!信息科学与工程学院例例 void main( ) char *string=“I love China!”; printf(“%sn”,string); string+=7; while( *string ) putchar(string0); string+; IloveChistringn!a0字符指针字符指针初始化初始化: :把字符串把字符串首地址首地址赋给赋给stringstring char *string; string=“I love China!”;str
25、ing*string!=0用字符指针指向一个字符串用字符指针指向一个字符串信息科学与工程学院字符串拷贝函数字符串拷贝函数假如有以下定义假如有以下定义 char source=“Hello”; char destination100;如何将数组如何将数组source中的内容复制到中的内容复制到destination数组中?数组中? destination = source 这样是否正确?这样是否正确?信息科学与工程学院void copy_string(char *from,char *to) for(;*from!=0;from+,to+) *to=*from; *to=0; void main
26、( ) char source=“Hello”,destiantion20copy_string(source, destiantion); printf(“s is %sn”, source); printf(“d is %sn”, destiantion); 例:自定义一个字符串复制函数例:自定义一个字符串复制函数信息科学与工程学院动态内存申请动态内存申请数据对象的动态申请数据对象的动态申请.ppt信息科学与工程学院需求需求求班级学生的平均成绩。求班级学生的平均成绩。班级人数在程序运班级人数在程序运行时才能确定。行时才能确定。信息科学与工程学院算法分析算法分析用户输入班级的人数,设为用户输
27、入班级的人数,设为n输入输入n位位学生的成绩学生的成绩求求n位位学生的总成绩和平均成绩学生的总成绩和平均成绩输出平均成绩输出平均成绩信息科学与工程学院带来的问题带来的问题学生人数在程序运行时才能确定,也就是说放学生人数在程序运行时才能确定,也就是说放置学生成绩的变量个数在编程时是不确定的。置学生成绩的变量个数在编程时是不确定的。如果使用数组放置,但数组定义中要求元素的如果使用数组放置,但数组定义中要求元素的个数必须确定,无法满足要求。个数必须确定,无法满足要求。信息科学与工程学院数据对象动态创建与释放的语句数据对象动态创建与释放的语句申请内存空间函数:申请内存空间函数:malloc函数函数 P
28、184 void *malloc(unsigned size);对对malloc函数的调用格式是:函数的调用格式是:(指针所指对象的数据类型指针所指对象的数据类型 *)malloc(sizeof (指针所指对象指针所指对象的数据类型的数据类型 *个数个数)malloc函数的功能是从内存中申请一块指定字节大小函数的功能是从内存中申请一块指定字节大小的连续空间,返回该存储空间(存储块)的首地址作的连续空间,返回该存储空间(存储块)的首地址作为函数的结果。如果申请空间失败,则说明没有足够为函数的结果。如果申请空间失败,则说明没有足够的空间可供分配,返回空指针的空间可供分配,返回空指针NULL。信息科
29、学与工程学院例例1:int *pi;pi=(int *)malloc(sizeof(int);例例2:int *pj;pj=(int *)malloc(sizeof(int)*10);作用:申请一个动态的整形存储单元作用:申请一个动态的整形存储单元作用:申请十个动态的整形存储单元作用:申请十个动态的整形存储单元信息科学与工程学院释放内存空间函数:释放内存空间函数: free函数函数 P185 void *free(void *p);对对free函数的调用格式是:函数的调用格式是: free(指针变量名指针变量名);free函数的功能是释放以指针变量名所指的位置函数的功能是释放以指针变量名所指的
30、位置开始的存储块,以分配时的存储块为基准。开始的存储块,以分配时的存储块为基准。free函数与函数与malloc函数必须配对使用,使用函数必须配对使用,使用malloc申请的空间必须用申请的空间必须用free释放。释放。信息科学与工程学院void main()float total,average, *pS;int n;printf(Please input the number of students:);scanf(%d,&n);pS = (float *)malloc(n * sizeof(float);for (i=0;in;i+)printf(Please input the num
31、 %d:,i+1);scanf(%f,pS);pS+; 例例3:动态内存申请与释放:动态内存申请与释放信息科学与工程学院注意事项注意事项在函数中定义的形参在函数中定义的形参int ppp相当于相当于 int *ppp信息科学与工程学院小结小结指针变量的定义方式?指针变量的定义方式?指针变量是否有类型?指针变量是否有类型?如何取变量的地址?如何取变量的地址?如何通过指针访问其指向变量的值?如何通过指针访问其指向变量的值?通过什么方式才能在被调函数中改变调用函数通过什么方式才能在被调函数中改变调用函数中变量的值?中变量的值?数组名代表什么含义?能给数组名赋值吗?数组名代表什么含义?能给数组名赋值吗
32、?指向数组的指针通过什么方式进行移动去访问指向数组的指针通过什么方式进行移动去访问数组中不同的元素?数组中不同的元素?信息科学与工程学院形参的中数组类型本质属于什么?形参的中数组类型本质属于什么?动态申请内存函数和释放内存函数的使用动态申请内存函数和释放内存函数的使用通过指针访问字符串数组时,跟访问一般通过指针访问字符串数组时,跟访问一般的数组有何不同之处?的数组有何不同之处?信息科学与工程学院课堂作业课堂作业1程序运行后,用户任意输入一个字符串,求出程序运行后,用户任意输入一个字符串,求出字符串长度,然后输出字符串内容及个数。字符串长度,然后输出字符串内容及个数。不能使用不能使用strlen
33、函数。函数。求字符串长度函数的函数原型必须如下:求字符串长度函数的函数原型必须如下:int MyStrLenPt(char *str)例如输入:例如输入:nihao123! 则输出:则输出:nihao123!: 9 chars信息科学与工程学院课堂作业课堂作业2 编写一个对一维数组进行排序的程序。编写一个对一维数组进行排序的程序。要求:要求:写两个函数,一个主函数,一个写两个函数,一个主函数,一个sort函数。在函数。在主函数中完成数组的输入和输出,通过调用主函数中完成数组的输入和输出,通过调用sort函数对数组进行排序函数对数组进行排序。 sort函数的原型为:函数的原型为: void so
34、rt(int *p, int n);信息科学与工程学院课外练习课外练习.225-226 1、2、3信息科学与工程学院上机实验七上机实验七 上机指导上机指导实验七实验七 指针指针实验内容:课堂作业实验内容:课堂作业1、2实验步骤:实验步骤:(1 1)先自学并完成上机指导实验)先自学并完成上机指导实验7 7 指针指针P129-134P129-134内容,内容,掌握指针相关的调试技巧;掌握指针相关的调试技巧;(2 2)完成并提交课堂作业)完成并提交课堂作业1 1、2 2的程序,的程序,可将两个程序可将两个程序的代码统一粘贴在一个的代码统一粘贴在一个WordWord文件中,文件中,文件的名称为:班文件
35、的名称为:班级级+ +学号后两位学号后两位+ +姓名姓名+ +实验七实验七.doc.doc。信息科学与工程学院*7.4 7.5 7.6 7.7学习要点学习要点信息科学与工程学院二级指针二级指针 char *p, ch=10,*pv; p = &ch; pv = &p;2000chppv200220061020002002信息科学与工程学院二维数组跟指针的关系二维数组跟指针的关系假如有假如有int a3; l a的意义?的意义?l a指向的数据对象是什么指向的数据对象是什么? a+1?假如假如int a24; l a的意义?的意义?l a指向的数据对象是什么?指向的数据对象是什么?a+1?l a0代表什么含义?代表什么含义?l a1代表什么含义代表什么含义?信息科学与工程学院指针数组指针数组char pp10;char pp10;char char * *pstr10;pstr10;