资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,*,C语言复习PPT,变量类型的转换,自动转换 发生在不同数据类型的变量混合运算时,由,编译系统,自动完成,强制转换 通过,类型转换运算,来实现,(,类型说明符,)(,表达式,),(int)(a+b),结合性,在表达式中,各运算量参与运算的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的制约,以便确定是自左向右进行运算还是自右向左进行运算,算术运算符的结合性是,自左至右,,即先左后右,:,x-y+z,赋值运算符是,右结合性,运算符:,x=y=z;,一、算术运算符,基本的算术运算符:,+-,*,/%,说明:,(,1,)在“”运算中,若操作数均为整数,则执行整除运算,舍去小数部分。例如:,5/3=1,(,2,)“”要求两侧均,为整数,“”运算不能用于,float,和,double,型数据,例如:,2,(3),的优先级高于,二、,自增、自减运算符,(、,-,),+i,-i,(,先加,/,减,1,,然后取,i,的值,),i+,i-,(,先取,i,的值,然后加,/,减,1,),b=2 ,a=2,b=2 ,a=3,作用:使变量的值增或减,如:,例如:,int a=1,b;,b=+a ;,b=a+;,先使用,i,的值,再执行,i=i+1,先执行,i=i+1,,再使用,i,的值,+i,i+,说明,:,1.+,、只能用于变量,不能用于常量或表达式。,例如:,10,,(,x+y)+,+,a,b+,中合法的为:,2.,自增、自减运算符为右结合性。,例如:,a+,b+,(,a+,),3.,常用于循环变量自动加,1,4.,表达式中运算符的组合,尽可能左结合,如:,I+J,(,I+,),+J,5.,表达式中使用自加或自减运算时,需注意,如:,I=3,K=,(,I+,),+,(,I+,),+,(,I+,),结果:,k,=9,I=6,如:,I=3,I,=,(,I+,),+,(,+I,),+,(,I+,),结果:,I=14,若,a=2,,,b=3,,,x=3.5,,,y=2.5,,则表达式,(float)(a,b)/2,(int)x%(int)y,的值是,3.5,表达式,1/4+2.75,的值是,2.75,三、赋值运算符和赋值表达式,1.,赋值运算符为,“,=,”,形式:变量名,=,常量或表达式,作用:将一个数据赋给一个变量,右结合性,例如:,a=3;b=c+d;,C,规定:,任何表达式在末尾加上分号就构成语句。,如:,A=B+C,表达式,A=B+C,;,语句,“=”,号两端数据类型不同时进行转换,转换是系统自动进行的,右边转换为左边类型。规则如下:,(,1,)整型,=,实型,舍去,小数部分,(,2,)实型,=,整型 值不变,以浮点形式存放,(,3,)整型,=,字符型 值放入低,8,位,高,8,位为,0,(,4,)字符型,=,整型 仅将整型低,8,位存入,六、关系运算符和关系表达式,语言中的关系运算符有种。(左结合性),、!,2.,算术运算符,(,高,),关系运算符,赋值运算符,(,低,),优先次序:,1.,前种同级,高于后种(后种同级),例如,:x!=y,、,s-db+c,、,a=bc,关系运算符运算出的结果为,0,或,1,0,,表示假,即该关系不成立,1,,表示真,即该关系成立,在所有涉及到真假判断的地方,,0,表示假,非,0,表示真,优先级:,!,高于,&,高于,|,混合运算中:,!,高,算术运算,关系运算,&,、,|,低,赋值运算,注:,如何判断一个逻辑表达式为“真、假”?,用“非”代表 “真”,用“”代表“假”。,如:,b&0,值为:“,0,”,逻辑表达式:,运算结果为逻辑值,编译系统以非,0,、,0,判定逻辑值真、假,逻辑表达式中作为参加逻辑运算的运算对象可以是,0,或非,0,数值。但要区分运算对象。,例:,53&2|8b,?,a,:,b,将条件表达式的值赋给变量,max,说明:,例:设,a,b,c,d,的值为,1,、,2,、,3,、,4,求下述表达式的值,max=ab?a:cd?c:d,等价于,max=ab?a:(cd?c:d),结果为:,4,优先级:,!,高于,&,高于,|,混合运算中:,!,高,算术运算,关系运算,&,、,|,低,赋值运算,表达式:,2,-2,的值是,1,设,x,、,y,和,z,是,int,类型变量,且,x=3,;,y=4,;,z=5,;则下面表达式中的值为,0,的是,。,A,x,&,y,B,x=y,C,x|y+z&y-z,D,!(x=A&x=a&x=z,while,while,(表达式)语句块1;语句块2;,只要,表达式,的值为,非0,,就重复执行,语句块1,,直到,表达式,值为,0,时止,开始执行,语句块2,表达式,!=0?,Y,N,语句块,1,语句块,2,for,for,(表达式1;表达式2;表达式3)语句块;,首先执行,表达式1,。如果,表达式2,的值为,非0,,就重复执行,语句块,和,表达式3,,直到,表达式2,的值为,0,时止,相当于:,表达式1;,while,(表达式2)语句块;表达式3;,for,的所有表达式均可省略,表达式,2!=0?,Y,N,语句块,表达式,3,表达式,1,注意,在,for,和,while,语句之后一般没有分号,有分号表示循环体就是分号之前的内容,即循环体不存在,while,(i 100),;,i+;,for,(i=0;i 100;i+),;,printf(%d,i);,for,通常有一个循环变量控制循环的次数,不要在循环体内改变这个变量,循环,do,-,while,do,语句块1;,while,(表达式);语句块2;,首先执行,语句,,然后判断,表达式,的值。如果表达式为,0,,继续向下执行,否则,再次执行,语句,,再次判断,表达式,的值,语句块1,会被执行至少一次,表达式,!=0?,Y,N,语句块,1,语句块,2,break,和,continue,对,for,、,while,、,do,-,while,循环进行内部手术,break,,,退出循环,continue,,,中断此次循环的执行,开始下一次,break,和,continue,少用为妙,它们增加了循环执行的分支,,break,更增加了循环的出口,它们可以用来处理程序异常,而尽量不要用来处理正常流程,若 int x=4,,,y=6,,,z=0,;有循环,while(x=y)z+,;,y,-,;,则循环语句执行完后,,z,值为,。,6,判断题:,1.,标准,C,中,并不区分英文字符的大小写。,2.,表达式“,ELSE,”是合法的,C,语言标识符。,错,对,若一自然数全部正整数因子(该因子不包括其本身)之和仍为该自然数,则该自然数称为完全数。如:6=1+2+3,,则,6,是完全数。,求,2,,,1000,以内的所有完全数。,main(),int x,n,m;,for(n=2;n=1000;n+),;,for(m=1;my?x:y);,函数可根据需要出现个,return,语句,(1)如果函数值类型与,return,语句表达式值的类型不一致,以函数类型为准(数值型会自动进行类型转换),(2),声明为void型的函数中不能包括带值的return 语句;主函数体内不能出现return语句。,注意:,注意:,(,3,)当函数没有return语句时,以结束函数的大括号 作为返回点。但这时并不表明函数没有返回值,这时的返回值是系统给的不确定值。,(,4,)除了空值函数以外的所有函数都返回一个值,那么我们是不是非得去使用这个返回值呢?答案是否定的。如果没有用它赋值,那它就被丢弃了。,(,5,)在同一函数内,可用根据需要在多处出现return语句,但函数第一次遇到return时就立即停止执行,并返回到主调函数,函数的调用,形式参数,:,在,定义,函数时函数名后面,括弧中的变量名,简称,形参,实际参数,:,在,调用,函数时函数名后面 括弧中的表达式,简称,实参,调用格式:,函数名,(,实参,表列,),说明:,实参,必须,有确定的值,形参,必须,指定类型,形参与实参,类型一致,个数相同,若形参与实参类型不一致,自动按形参类型转换,函数调用转换,形参在函数被调用前不占内存,;,函数,调用时,为形参,分配内存,;调用,结束,,内存,释放,函数参数及其传递方式,值传递,方式,方式:函数调用时,为形参分配单元,并将实参的值,复制,到形参中;,调用结束,形参单元被释放,,实参单元仍保留并维持原值,,形参作域只限函数内,特点:,形参与实参占用,不同,的内存单元,单向,传递,参数传递方式,方式:函数调用时,将数据的,存储地址,作为参数传递给形参,特点:,形参与实参占用,同样,的存储单元,“双向”,传递,实参和形参必须是,地址,常量或变量,函数的地址传递,递归调用,函数在它的函数体内调用自己,以实现层次数据结构的查询和访问,使用递归的条件:,1,一个问题可以逐步解决,并且每一步的解决方法一样,,只是问题的参数有规律的变化,2,有一个明确的结束递归的条件,优点:,递归的使用可以使代码更简洁清晰,可读性更好,缺点:,由于递归需要系统堆栈,所以空间消耗要比非递归代码要大很多,,而且,如果递归深度太大,可能系统资源会不够用,方便了程序员难为了机器,所有的递归函数都可以转换为迭代函数,反之亦然,概述,变量,是对程序中数据的存储空间的抽象,内存,.,main(),int a;,a=10;,printf(“%dn”,a);,printf(“%dn”,&a),编译或函数调用时为其分配内存单元,10,2000,2001,程序中使用变量名对内存操作,6.6,变量的存储属性,6.6.1变量的作用域与生存期,C语言中变量必须先定义后使用,变量的数据类型决定了计算机为变量预留多少存储空间以及该变量上应具有的一组运算。,C语言中,除了对变量进行数据类型说明,还可以说明变量的存储类型。不同的存储类型可以确定一个变量的作用域和生存期。,变量的存储类型,1.变量的作用域,变量的作用域是指变量的作用范围,在C语言中分为在全局有效、局部有效和复合语句内有效三种。,语言中所有的变量都有自己的作用域。变量说明的位置不同,其作用域也不同,据此可将语言中的变量分为局部变量(内部变量)和全局变量(外部变量)。,2.,生存期,变量的生存期是指变量作用时间的长短,在C语言中分为,程序期,、,函数期,和,复合期,三种。,变量的属性,数据类型:变量所持有的数据的性质(,操作属性,),存储属性,存储器类型:寄存器、静态存储区、动态存储区,生存期,:变量在某一时刻存在,-,静态变量与动态变量,作用域,:变量在某区域内有效,-,局部变量与全局变量,变量的存储类型,auto -,自动型,register-,寄存器型,static -,静态型,extern -,外部型,变量定义格式,:,存储类型,数据类型 变量表,;,数据类型,存储类型,变量表,;,static int x,y;,局部变量,定义:在函数内定义,只在本函数内有效,说明:,main,中定义的变量只在,main,中有效,不同函数中同名变量,占不同内存单元,形参属于局部变量,可定义在复合语句中有效的变量,局部变量可用存储类型:,auto,register static,(默认为,auto,),#include,main(),int Test_Var=1;,int Test_Var=2;,int Test_Var=3;,printf(“%dn”,Test_Var);,/*?*,printf(“%dn”,Test_Var);,/*?*,printf(“%dn”,Test_Var);,/*1*,1.,自动变量,在函数内部或复合语句内部定义的变量,如果没有写明存储类,或使用了auto说明符,系统就认为所定义的变量具有自动变量类别,有时也称(动态)局部变量。,形参属于被调用函数的局部变量。注意:形参缺省的关键字是auto,但不能将auto直接加在形参之前。,自动变量的初始化是:每一次调用,形参都以实参为初值,非形参的自动变量在函数体内部或复合语句内部都重新赋初值。所以,未赋初值的自动变量,“无定义”,其值不定。,3.静态局部变量,在函数体(或复合语句)内部,用以下定义格式定义的变量称为静态局部变量:,static数据类型 变量表;,例如:static int a=8;,静态局部变量的初始化只在编译时进行,一次,,每次调用它们所在的函数时,不再重新赋初值,,只是保留上次调用结束时的值,。若定义但不初始化,则自动赋以(数值型)或0(字符型)。,例6.18,求下列程序的输出结果,#include,main(),int f(void);/*函数声明*/,int j;,for(j=0;j3;j+),printf(%dn,f();,int f(void)/*无参函数*/,static int x=1;,x+;,return x;,程序运行结果:,2,3,4,例,:分析执行结果,f(int a),int b=0;static int c=3;,b+;c+;,printf(“%5d%5d%5d”,a,b,c);,return(a+b+c);,main(),int a=2,k;,for(k=0;k3;k+),printf(“%5dn”,f(a);,静态变量只初始化一次,结果:,2 1 4 (a,b,c),7 (f(a),2 1 5,8,2 1 6,9,2.静态全局变量,当用static说明符说明全局变量时,此变量就称为静态全局变量或静态外部变量。,此时static的作用不是把全局变量改为静态存储,因为它本身就是静态存储类,而是限制了它的作用域只能在本文件内,不能用extern说明符使其作用域扩展到程序的其它文件中。,静态外部变量允许程序的一部分对其它部分充分隐蔽,这有利于管理大型复杂程序,程序员不必担心因全局变量重名而引起混乱。,静态,动态,存储方式,程序整个运行期间,函数调用开始至结束,生存期,编译时赋初值,,只赋一次,每次函数调用时,赋初值,自动赋初值,0,或空字符,不确定,未赋初值,静态存储区,动态区,存储区,寄存器,局部变量,外部变量,作用域,定义变量的函数或复合语句内,本文件,其它文件,局部变量默认为,auto,型,register,型变量个数受限,且不能为,long,double,float,型,局部,static,变量具有,全局寿命,和,局部可见性,局部,static,变量具有,可继承性,extern,不是变量定义,可扩展外部变量作用域,register,局部,static,auto,外部,static,外部,存储类别,变量存储类型,找出,2,个错误,用递归语句编函数计算,10,!,long f(int m),long a;,if(m0)printf(“data error!”);,else a=f(m,1)*m;,main(),int n;,n=10;,printf(“%d!=%ld”,n,f(n);,if(m=0)a=1;,return(a);,用递归语句编函数计算,6,!,long f(int m),long a;,if(m0)printf(“data error!”);,else a=f(m-1)*m;,main(),int n=6;,printf(“%d!=%ld”,n,f(n);,if(m=0)a=1;,return(a);,#include,int i=0;,main(),int k=1;,i+;,k+;,printf(“good i=%d,k=%dn”,i,k);,sub();,sub();,static int y=0;,sub(),int k=0;static int x=1;,y+;,k+;,x+;,printf(“bad i=%d,k=%d,x=%d,y=%dn”,i,k,x,y);,good i=1,k=2,bad i=1,k=1,x=2,y=1,bad i=1,k=1,x=3,y=2,一维数组的定义,定义方式:,数据类型 数组名,常量表达式,;,合法标识符,表示元素个数,下标从,0,开始,:,数组运算符,单目运算符,优先级,(1),左结合,不能用,(),例,int a6;,a0,0,1,4,5,a1,a2,a3,a4,a5,2,3,a,编译时分配连续内存,内存字节数,=,数组维数*,sizeof(,元素数据类型,),数组名表示内存首地址,,是,地址常量,一维数组,.,4的高位字节,4的低位字节,2的高位字节,2的低位字节,2000,2002,2004,2006,2008,a0,a1,a2,a3,a4,数组在内存中的首地址,即,a=2000,int a5=2,4,23,6,78;,二维数组的定义,定义方式:,数据类型数组名,常量表达式,常量表达式,;,数组元素的存放顺序,原因,:,内存是一维的,二维数组:按行序优先,多维数组:最右下标变化最快,例,int a34;,float b25;,int c234;,int a3,4;,(,),行数,列数,元素个数,=,行数*列数,int a32,a,0,1,a,1,0,a,1,1,a,2,0,a,2,1,0,1,4,5,2,3,a,0,0,a00 a01,a10 a11,a20 a21,int c234,0,1,2,3,4,5,6,7,.,20,21,22,23,c000,c001,c002,c003,c010,c011,c012,c013,c020,c021,c022,c023,c100,c101,c102,c103,c110,c111,c112,c113,c120,c121,c122,c123,二维数组及多维数组,引用,例,aij,(i:,0,N-1,j:,0,M-1),初始化,例,int a23=,1,2,3,4,5,6,;,a00,a01,a02,a10,a11,a12,1,2,3,4,5,6,分行全部赋初值,例,int a23=,1,2,3,4,5,6,;,a00,a01,a02,a10,a11,a12,1,2,3,4,5,6,全部元素赋初值,例,int a,3=,1,2,3,4,5,;,a00,a01,a02,a10,a11,a12,1,2,3,4,5,0,全部元素赋初值第一维可省,例,int a23=,1,2,4,;,a00,a01,a02,a10,a11,a12,1,2,4,0,0,0,部分元素赋初值,例,int a3=,1,4,5,;,a00,a01,a02,a10,a11,a12,1,0,0,4,5,0,赋初值时指定维数第一维可以省略,例,int a23=,1,2,4,;,a00,a01,a02,a10,a11,a12,1,2,0,4,0,0,分行部分赋值,字符数组,定义:,初始化,逐个字符赋给数组中的元素,;,利用字符串常量,.,例,char c10,ch34;,例,char ch,6,=,Hello,;,char ch6=,Hello,;,char ch=,Hello,;,字符串常量初始化,ch0,H,e,l,l,o,ch1,ch2,ch3,ch4,0,ch5,例,char ch5=,Boy,;,ch0,B,o,y,0,0,字符串常量初始化,ch1,ch2,ch3,ch4,例,char ch5=,B,o,y,;,ch0,B,o,y,0,0,逐个字符初始化,ch1,ch2,ch3,ch4,例,char ch5=,H,e,l,l,o,;,ch0,H,e,l,l,o,逐个字符初始化,ch1,ch2,ch3,ch4,例,char diamond,5=.,.,*,.,*,.,*,*,.,.,.,*,.,*,.,*,.,.,*;,二维数组初始化,.,.,*,0,0,.,*,.,*,0,*,.,.,.,*,.,*,.,*,0,.,.,*,0,0,diamond0,diamond1,diamond2,diamond3,diamond4,例,char fruit,7=Apple,Orange,Grape,Pear,Peach;,二维数组初始化,fruit0,fruit1,fruit2,fruit3,fruit4,A,p,p,l,e,0,0,O,r,a,n,g,e,0,G,r,a,p,e,0,0,P,e,a,r,0,0,0,P,e,a,c,h,0,0,字符串,:,没有字符串变量,字符串用字符数组来处理,;,一个字符串用,0,作结束标志。,(,或空字符,),例,“,hello”,有,5,个字符,存储在,6,个字符的字符,数组中。,char,a=“hello”,h e l l o,0,输入输出字符串,字符的,输入,/,输出:,%c,字符串的,输入,/,输出:,%s,例,使用,%c,main(),char str5;,int i;,for(i=0;i5;i+),scanf(“%c”,&,stri);,for(i=0;i5;i+),printf(“%c”,stri);,例,使用,%s,main(),char str5;,scanf(“%s”,str,);,printf(“%s”,str,);,使用数组名,不需使用地址运算符,&,输入字符串的长度,数组的长度,用,空格,或,换行结束输入,自动添加结束符,0,使用数组名,用,0,标志字符串的结束,字符串处理函数,puts,(,字符数组名,),stdio.h,puts,输出字符串,可以包含转义字符,;,字符数组必须具有字符串结束标记,0,gets,(,字符数组名,),stdio.h,gets,输入一个字符串到字符数组,换行表示,输入字符串结束,;,自动在输入字符串后加入结束标志,0,;,字符串长,=,数组长度,函数的返回值是数组的首地址,一般不关心。,只输入一个字符串。,例,#include,main(),char string80;,printf(,Input a string:,);,gets(string);,puts(string);,input:,How are you?,output:,How are you?,strcat,(,字符数组名,1,字符数组名,2),string.h,将,字符数组,2,连接到,字符数组,1,的后面,连接时,自动取消,字符数组,1,后面的结束标志,;,结果存放到,字符数组,1,中,函数返回值是,字符数组,1,的首地址,;,字符数组,1,要有足够的空间存放结果,;,strcpy,(,字符数组,1,字符串,2),string.h,将,字符串,2,复制到,字符数组,1,包括,0,;,字符数组,1,必须有足够的空间存放结果,;,字符串,2,可以是数组名。,可以将字符串,2,前面的若干个字符赋值到字符数组,1,中去。,不能用赋值语句将一个字符串赋值给字符数组,例,char str120,str220;,str1=,Hello!,;,(,),str2=str1;,(,),例,:strcpy,和,strcat,#include,#include,main(),char destination25;,char blank=,c=C+,turbo=Turbo;,strcpy(destination,turbo);,strcat(destination,blank);,strcat(destination,c);,printf(%sn,destination);,Turbo C+,T,r,b,o,C,+,+,0,1,2,3,4,5,6,7,8,9,u,0,24,.,T,r,b,o,0,1,2,3,4,5,6,7,8,9,u,0,24,.,.,T,r,b,o,0,0,1,2,3,4,5,6,7,8,9,u,24,.,.,strcmp,(,字符串,1,字符串,2),string.h,用字符的,ASCII,值,逐个对应比较,字符串,1,与,字符串,2,字符的大小,(left-to-right),;,if,字符串,1,字符串,2,返回,字符串,2,返回,0,;,不能用,=,去直接比较两个字符串的大小,.,strlen,(,字符数组,),string.h,返回字符串的长度,;,函数的值是字符串的实际长度,不包括,0,.,例,strlen(s),的结果:,(1),char s10=,A,0,B,C,0,D,;,结果:1,已知矩阵,a=,,求该矩阵对角线元素之和。,main(),int i;,int a33=1,2,3,4,5,6,7,8,9;,for(i=1;i=3;i+),sum=sum+ii;,printf(“sum=%d”,sum);,int sum=0;,for(i=0;i3;i+),已知质数的定义是:若某一正整数只有1和它本身两个因子,则这个正整数称为质数。例如13只有1和13两个因子,则13为质数。数学上规定1不是质数。若整数A是整数B的因子,且整数A是质数,则称A是B的质因子。例如整数36的质因子为2,3。编写程序求整数12903的最大质因子。,f(int x),int i;,for(,;ix;i+),if(x%i=0),k=2;break;,return(k);,main(),int n=12903,b,a;,for(a=2;an;a+),if(f(a)=1)&(n%a=0),printf(“the answer is%dn”,b);,int k=1,i=2,b=a;,指针变量定义,定义指针变量的一般形式为,基类型,*,指针变量名,指针变量与普通变量类似,在程序中若要使用指针变量,必须先进行定义后使用。,例如:,int *p1,i;(定义p1为指向整型变量的指针变量),char *p2,c;(定义p2为指向字符型变量的指针变量),float *p3,f;(定义p3为指向实型变量的指针变量),int、char、float分别称为指针变量p1、p2、p3的,“,基类型,”,,,.,.,2000,2004,2006,2005,整型变量,i,10,变量,i,_pointer,2001,2002,2003,指针与指针变量的区别?,指针:一个变量的,地址,指针变量:专门存放,变量地址的变量,叫,2000,指针,指针变量,变量的,内容,变量的,地址,指针变量,变量,变量地址,(,指针,),变量值,指向,地址存入,指针变量,&与*运算符,含义,含义,:,取变量的地址,单目运算符,结合性,:,自右向左,含义,:,取指针所指向变量的内容,单目运算符,结合性,:,自右向左,两者关系:互为,逆运算,理解,.,.,2000,2004,2006,2005,整型变量,i,10,变量,i,_pointer,2001,2002,2003,2000,指针变量,i_pointer,-,指针变量,它的内容是地址量,*,i_pointer,-,指针的,目标变量,,它的内容是数据,&,i_pointer,-,指针变量占用内存的地址,2000,10,i_pointer,*i_pointer,&i_pointer,i,i_pointer&i&(*i_pointer),i *i_pointer *(&i),i_pointer,=,&i,=,&(*i_pointer),i,=,*i_pointer,=,*(&i),直接访问与间接访问,直接访问:按变量地址存取变量值,间接访问:通过存放变量地址的变量去访问变量,例,i=,3,;,-,直接访问,指针变量,.,.,2000,2004,2006,2005,整型变量,i,10,变量,i,_pointer,2001,2002,2003,2000,3,例,*,i_pointer=,20,;,-,间接访问,20,指针变量,.,.,2000,2004,2006,2005,整型变量,i,10,变量,i,_pointer,2001,2002,2003,2000,整型变量,k,例,k=i;,-,直接访问,k=*i_pointer;,-,间接访问,10,例,k=i;,k=*i_pointer;,指针变量赋值(初始化),1,通过取地址运算符(&)获得地址值,如下定义和赋值:,int a=5,*p,*q;,p=,它建立了如图所示的逻辑关系,p,a,&a,5,因此当有语句:,p=,时,,scanf(%d,和,scanf(%d,p),是等价的,2,通过指针变量获得地址值,可以通过赋值运算,把一个指针变量中的地址值赋给另一个指针变量,从而使这两个指针变量指向同一地址,q=p;,使指针变量,q,中也存放了变量,a,的地址,也就是说指针变量,p,和,q,都指向了整型变量,a,赋值号两边指针变量的基类型必须相同,p,a,q,&a,5,&a,3,给指针变量赋“空”值,p=NULL;,p=0;,NULL,的代码值为,0,,,应当注意:,1.,指针变量只能存放地址,不能把一个整型量赋给指针变量,p=5;,应该通过取地址运算符“,&”,把一个地址赋给指针变量。,2.,应避免使用没有赋值的指针变量,没有赋值的指针变量虽不会导致编译出错,但可能导致无法预料的灾难性后果,注意:,),指针变量数据类型必须与所赋值的变量类型一致,,例如以下语句是非法的。,float y;int*p;p=,因为为,整型指针变量,,y为,实型变量,,,类型不一致,,故为p=&y;是,非法,语句。,),不允许把一个数(常量)赋予指针变量,,故下面的赋值是错误的。,int*p;p=1000;,),被赋值的指针变量前不能再加“*”说明符,,如写为*p=&a 也是错误的。,但对于在定义指针的同时赋值是允许的,,如:int*p=其实质可分解为两句,即:,int*p;p=,),可以将指针变量初始化为空值NULL,。如:,p=NULL;,为进一步明确运算符“&”和“*”的含义和作用,思考下面几个问题:,)如果已经执行了p=语句,则&*p的含义是什么?,假设已经执行了p=语句,则(*p)+相当于a+,即将指针变量p所指示的变量的值加1。而*p+等价于*(p+),这时先将p的值加1,p不再指向a了,而是指向a所占用存储区域的后续位置,再取其内存值。,)如int i=5,*p;再执行*i运算可不可以?,由于运算符“”和“*”的优先级相同,按自右而左的方向结合,因些进行*p的运算,即得到变量a的值,再执行运算。因此,*p与a、p是等价的。即可以说“”与“*”是互为反运算。,这是不允许的,因为i只是一个整型变量,而不是指针变量,故根据自右而左的运算*i是错误的,*运算符只能是对指针变量进行运算。,3)(*p)+和*p+的区别是什么?,数组元素表示方法,a0,a1,a2,a3,a9,.,a,a+9,a+1,a+2,地址,元素,下标法,a0,a1,a2,a9,a0,a1,a2,a3,a9,.,p,p+9,p+1,p+2,地址,元素,指针法,*p,*(p+1),*(p+2),*(p+9),变址运算符,a,i,*(a+i),ai,pi,*(p+i),*(a+i),*a,*(a+1),*(a+2),*(a+9),p0,p1,p2,p9,数组名作函数参数,数组名作函数参数,是,地址传递,数组名作函数参数,实参与形参的对应关系,实参,形参,数组名,指针变量,数组名,指针变量,数组名,数组名,指针变量,指针变量,字符串与数组关系,字符串用一维字符数组存放,字符数组具有一维数组的所有特点,数组名是指向数组首地址的地址常量,数组元素的引用方法可用指针法和下标法,数组名作函数参数是地址传递等,区别,存储格式:字符串结束标志,赋值方式与初始化,输入输出方式:%s%c,char str=,Hello!,;(,),char str=,Hello!,;,(,),char str=,H,e,l,l,o,!,;,(,),char *cp=,Hello,;,(,),int a=1,2,3,4,5;,(,),int *p=1,2,3,4,5;(,),char str10,*cp;,int a10,*p;,str=,Hello,;(,),cp=,Hello!,;,(,),a=1,2,3,4,5;,(,),p=1,2,3,4,5;,(,),scanf(“%s”,str);,printf(“%s”,str);,gets(str);,puts(str);,二维数组和指针变量,指向数组元素的指针变量,定义一个二维数组:,int a23=1,2,3,4,5,6;,二维数组元素在内存中是按行存放的,对于上面的定义我们可以认为a是数组名,数组包括2行即2个元素a0,a1。每个元素又是一维数组,包含3个元素,a,a0,a1,1,2,3,4,5,6,a02,*(a0+2),*(*(a+0)+2),指向指针的指针,定义:指向指针的指针,一级指针:指针变量中存放目标变量的地址,p1,&p2,&i,3,P2(,指针变量),i(,整型变量,),例,int,*,p1;,int *p2;,int i=3;,p2=,p1=,*p1=5;,二级指针,:,指针变量中存放一级指针变量的地址,例,int *p;,int i=3;,p=,*p=5;,&i,3,P(,指针变量),i(,整型变量,),一级指针,单级间接寻址,二级指针,一级指针,目标变量,二级间接寻址,定义形式:,存储类型,数据类型,*,指针名;,如,char *p;,例,int i,*p;,p=(,)/p,是二级指针,不能用变量地址为其赋值,指针本身的存储类型,最终目标变量的数据类型,*p,是,p,间接指向对象的地址,*,p,是,p,间接指向对象的值,例,int i=3;,int *p1;,int,*,p2;,p1=,p2=,*p=5;,i,p1,p2,3,&i,&p1,*p2,*p1,*p2,多级指针,例 三级指针,int *p;,四级指针,char *p;,例 用二级指针处理字符串,void main(),char*p;,char*name=Follow me,BASIC,Great Wall,FORTAN;,int i;,for(i=0;i4;i+),p=name+i;,printf(%x%sn,*p,*p);,name0,name1,name2,name3,name4,char*name5,Great Wall,FORTAN,0,Follow me,BASIC,name,p,指向函数的指针,函数指针:函数在编译时被分配的入口地址,用函数名表示,max,.,指令,1,指令,2,函数指针变量赋值,:,如,p=max;,函数返回值的数据类型,专门存放函数入口地址,可指向返回值类型相同的不同函数,指向函数的指针变量,定义形式:,数据类型,(,*,指针变量名,),();,如,int (*p)();,函数指针变量指向的函数必须有,函数说明,函数调用形式:,c=max(a,b);,c=,(*p),(a,b);,c=p(a,b);,对函数指针变量,p,n,p+,p-,无意义,(),不能省,int(*p)(),与,int *p(),不同,下列定义的含义,(1)int *p3;,(2)int (*p)3;,(3)int *p(int);,(4)int (*p)(int);,(5)int *(*p)(int);,(6)int(*p3)(int);,(7)int *(*p3)(int);,函数指针数组,函数返回,int,型指针,指向函数的指针,函数返回int,型变量,指向函数的指针,函数返回int,型指针,函数指针数组,函数返回,int,型变量,指针数组,指向一维数组的指针,返回指针的函数,1.,若有说明:int*p,m=5,n;以下正确的程序段是,:,Ap=&n;scanf(“%d”,&p);Bp=&n;scanf(“%d”,*p);,Cscanf(“%d”,&n);*p=n;,Dp=&n;*p=m;,2.,已知变量定义和函数调用语句:int a=25;print_value(&a);下面函数正确输出结果是,:,void print_value(int*x),printf(“%dn”,+*x);,A23 B24 C25 D26,选择,D,D,以下对a5元素的非法表示是:,int a10,*p=a;,A*(a+5)Bp+5 C*(p+5)Dp5,B,若已有定义:int a10;int*p;p=
展开阅读全文