《C语言复习》PPT课件.ppt

上传人:xt****7 文档编号:1792923 上传时间:2019-11-06 格式:PPT 页数:104 大小:1.04MB
返回 下载 相关 举报
《C语言复习》PPT课件.ppt_第1页
第1页 / 共104页
《C语言复习》PPT课件.ppt_第2页
第2页 / 共104页
《C语言复习》PPT课件.ppt_第3页
第3页 / 共104页
点击查看更多>>
资源描述
c语言复习,标识符注意事项,标识符用来命名变量、函数或类型; 由英文字母、数字和下划线组成,大小写敏感; 不可以是数字开头; 命名原则1直观,见名知意,便于记忆和阅读 最好使用英文单词或其组合 切忌使用汉语拼音 命名原则2可用下划线或大小写来增强可读性 variablename variable_name VariableName, variableName 不允许使用关键字作为标识符的名字 int, float, for, while, if等 某些功能的变量采用习惯命名 如:for语句所采用的循环变量习惯用i, j, k,变量类型的转换,自动转换 发生在不同数据类型的变量混合运算时,由编译系统自动完成 强制转换 通过类型转换运算来实现 (类型说明符) (表达式) (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)(ab)/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|84 ! =0 值为 1,逻辑表达式与关系表达式的区别: 逻辑表达式: 关心的是表达式的值 用表达式的值等于0或不等于0来判断条件是否成立. 不等于0,则结果为“真”; 等于0,则结果为“假” 例: int x = -2; if x printf(“ hello“); / * 结果为输出hello */,条件运算:根据条件确定某个表达式结果 的值。(C语言中唯一 的一个 三目运算) 运算符:?和 : 条件表达式形式: 表达式1?表达式2:表达式3,八、条件运算符和条件表达式,执行过程:,(2)结合方向为“右到左”,(1)条件运算优于赋值运算 如:max=ab ? 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的是 。 Ax&y Bx=y Cx|y+z&y-z D!(xy)&!z|1),D,格式:printf(“格式控制串”,输出表) 功能:按指定格式向显示器输出数据 返值:正常,返回输出字节数;出错,返回EOF(-1),格式输出函数,输出表:要输出的数据(可以没有,多个时以“,”分隔) 格式控制串:包含两种信息: 1.格式说明: %修饰符格式字符 ,用于指定输出格式 2.普通字符或转义序列:原样输出格式字符,int a=567;printf ( “%d”,a);,int a=255;printf(“%x”,a);,int a=65;printf(“%o”,a);,int a=567;printf(“%u”,a);,char a=65;printf(“%c”,a);,printf(“%s”,“ABC”);,float a=567.789;printf(“%e”,a);,float a=567.789;printf(“%f”,a);,float a=567.789;printf(“%g”,a);,printf(“%”);,567,ff,101,567,A,ABC,5.677890e+02,567.789000,567.789,%,说明 格式字符要用小写 格式字符与输出项个数应相同,按先后顺序一一对应 格式字符与输出项类型不一致,自动按指定格式输出,表格,格式: scanf(“格式控制串”,地址表) 功能:按指定格式从键盘读入数据,存入地址表指定的 存储单元中,并按回车键结束 返值:正常,返回输入数据个数,地址表:变量的地址,常用取地址运算符& 格式字符:d,i,o,x,u,c,s,f,e,例 scanf(“%d”, 输入:10 则 a=10,例 scanf(“%x”, 输入:11 则 a=17,格式输入函数,语句块(Block),括住的若干条语句构成一个语句块 语句块内可以定义变量 变量必须在语句块的开头定义 变量仅在定义它的语句块内(包括下层语句块)有效(scope.c) 同一个语句块内的变量不可同名,不同语句块可以同名(homonym.c) 各司其职、下层优先 尽量不要在下层语句块内定义变量,也尽量不要定义同名变量 语句块可以用在任何可以使用语句的地方,但没有道理要乱加语句块,if-else,选择结构的一种最常用形式 if (表达式) 语句块1; else 语句块2; 语句块3 表达式值非0时,执行语句块1,然后语句块3; 表达式值为0时,执行语句块2,然后语句块3 else部分可以没有。当表达式值为0时,直接执行语句3 if-else嵌套使用时,注意else和谁配套的问题,else-if,if的一种扩展 if (表达式1) 语句块1; else if (表达式2) 语句块2; else if (表达式3) 语句块3; else 语句块4; 语句块5; else部分可以没有,switch,多路选择 switch (表达式) case 整型常数1: 语句1; case 整型常数2: 语句2; default: 语句3; default可以没有 不要忘记break,说明: 1. switch结构的执行部分是一个由一些case子句和一个可缺省的default子句组成的复合语句,特别注意要用一对“”括起来。 2. switch后面的表达式一般是整型表达式或字符型表达式,与之相对应的case后面的常量表达式也应是一个整型表达式或字符型表达式,但要注意case与常量表达式之间要有空格。例如:case 6+9 : printf( “ok” ) ;是合法的。,3.在执行switch语句时,根据其后表达式的值找相匹配的case子句,要注意“case 常量表达式”只是起语句标号的作用,并不是在该处进行条件判断。当找到相匹配的case子句即入口标号时,就从此标号开始执行后面的语句。因此,应该在执行一个case子句后必须增加一条间断语句break来使流程跳出switch结构。如果未找到相匹配的case子句就执行default子句,若default子句放在最后其后可以不加break语句。 4.各个case子句出现的次序对执行结果没任何影响,即顺序可以任意布局。,5.每一个case能够拥有一条或多条语句,其最大的不同之处在于使用多条语句时不需要用“”括起来。 6.多个case可以共用一组执行语句。例如: case A: case a: +count ; break ; 成绩为大写字母A或小写字母a都进行累加求和。 7. switch结构中的case子句中的常量表达式的值不允许相同。 8. switch结构允许嵌套。,输入一个字符,若是小写字母就输出对应的大写字母,若是大写字母就输出对应的小写字母,如果其它字符,则输出错误提示。,main() char x; printf(“Input:“); ; if (x=A ,scanf(“%c“,x=a & x=z,while,while (表达式) 语句块1; 语句块2; 只要表达式的值为非0,就重复执行语句块1,直到表达式值为0时止,开始执行语句块2,for,for (表达式1; 表达式2; 表达式3) 语句块; 首先执行表达式1。如果表达式2的值为非0,就重复执行语句块和表达式3,直到表达式2的值为0时止 相当于: 表达式1; while (表达式2) 语句块; 表达式3; for的所有表达式均可省略,注意,在for和while语句之后一般没有分号 有分号表示循环体就是分号之前的内容,即循环体不存在 while (i 100); i+; for (i = 0; i 100; i+); printf(“%d“, i); for通常有一个循环变量控制循环的次数,不要在循环体内改变这个变量,循环do-while,do 语句块1; while (表达式); 语句块2; 首先执行语句,然后判断表达式的值。如果表达式为0,继续向下执行,否则,再次执行语句,再次判断表达式的值 语句块1会被执行至少一次,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; mn; m+) if(n%m = = 0) x = x + m; ; printf(“%dn”,n); ,x=0;,if(x= = n),函数 为实现一个特定的目的而编写的一个可被调用的的方法或过程 在C程序设计中,通常将一个较大程序分成几个功能较为单一的子程序模块,用函数来完成每个子程序的作用。C语言是函数驱动语言,C程序都由一个或多个函数构成,其中有且只有一个名为main的函数,即主函数,C程序总是从main函数开始执行并最后在main函数中结束整个程序的运行。 函数的作用 使程序变得更加易读、便于理解 节约空间、提高性能 提高可移植性 便于实现模块化设计 。,函数常识,1、功能模块:求解较小问题的算法和程序称作“功能模块”, 各功能模块可以先单独设计,然后将求解所有子问题的模块组合成求解原问题的程序。 2、一个解决大问题的程序,可以分解成多个解决小问题的模块,这就是“自顶向下”的模块化程序设计方法。 3、用一个或多个函数来实现这些功能模块。,注意:,(1)函数名和形式参数都是用户命名的标识符。在同一程序中,函数名必须唯一;形式参数只要在同一函数中唯一即可,可以与其它函数中的变量同名。 (2)语言规定,不能在一个函数的内部再定义函数。 (3)对函数类型的说明,必须与return语句中返回值表达式的类型一致。如果不一致,则以函数类型为准,由系统自动进行转换。如果缺省函数类型,则系统一律按int类型处理。,注意:,(4) 空函数既无参数、函数体又为空的函数。其一般形式为: 函数类型 函数名(void) 如:dump() (5) 带参数的形式参数表中类型和变量必须成对出现,如下面的定义是错误的: double add(double x,y),函数的定义,函数定义的一般形式 函数返回值的数据类型 函数名(类型名 变量名1,类型名 变量名2,) 声明部分 处理语句 【注意】函数名、一对圆括号不能省略,类型标识符,形参表,6.2.2 函数的返回值,语言的函数兼有其它语言中的函数和过程两种功能,从这个角度看,又可把函数分为有返回值函数和无返回值函数两种。 函数返回到函数调用点: 执行到函数结束的右花括号时(如果函数没有返回值); 执行到如下语句: return 表达式; 形式:return; return (x); return (x+y); return (xy?x:y); 函数可根据需要出现个return语句,(1)如果函数值类型与return语句表达式值的类型不一致,以函数类型为准(数值型会自动进行类型转换) (2)声明为void型的函数中不能包括带值的return 语句;主函数体内不能出现return语句。,注意:,注意:,(3)当函数没有return语句时,以结束函数的大括号 作为返回点。但这时并不表明函数没有返回值,这时的返回值是系统给的不确定值。 (4)除了空值函数以外的所有函数都返回一个值,那么我们是不是非得去使用这个返回值呢?答案是否定的。如果没有用它赋值,那它就被丢弃了。 (5)在同一函数内,可用根据需要在多处出现return语句,但函数第一次遇到return时就立即停止执行,并返回到主调函数,函数的调用,形式参数:在定义函数时函数名后面 括弧中的变量名,简称形参 实际参数:在调用函数时函数名后面 括弧中的表达式,简称实参 调用格式:函数名(实参表列),说明: 实参必须有确定的值 形参必须指定类型 形参与实参类型一致,个数相同 若形参与实参类型不一致,自动按形参类型转换函数调用转换 形参在函数被调用前不占内存;函数调用时为形参分配内存;调用结束,内存释放,函数参数及其传递方式,值传递方式 方式:函数调用时,为形参分配单元,并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值,形参作域只限函数内 特点: 形参与实参占用不同的内存单元 单向传递,参数传递方式,方式:函数调用时,将数据的存储地址作为参数传递给形参 特点: 形参与实参占用同样的存储单元 “双向”传递 实参和形参必须是地址常量或变量,函数的地址传递,递归调用,函数在它的函数体内调用自己,以实现层次数据结构的查询和访问,使用递归的条件: 1一个问题可以逐步解决,并且每一步的解决方法一样, 只是问题的参数有规律的变化 2有一个明确的结束递归的条件,优点: 递归的使用可以使代码更简洁清晰,可读性更好 缺点: 由于递归需要系统堆栈,所以空间消耗要比非递归代码要大很多, 而且,如果递归深度太大,可能系统资源会不够用 方便了程序员难为了机器,所有的递归函数都可以转换为迭代函数 ,反之亦然,概述 变量是对程序中数据的存储空间的抽象,编译或函数调用时为其分配内存单元,10,程序中使用变量名对内存操作,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说明符使其作用域扩展到程序的其它文件中。 静态外部变量允许程序的一部分对其它部分充分隐蔽,这有利于管理大型复杂程序,程序员不必担心因全局变量重名而引起混乱。,局部变量默认为auto型 register型变量个数受限,且不能为long, double, float型 局部static变量具有全局寿命和局部可见性 局部static变量具有可继承性 extern不是变量定义,可扩展外部变量作用域,变量存储类型,找出2个错误,用递归语句编函数计算10! long f (int m) long a; if(m0) printf(“data error!”); else a=f(m1)*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;,编译时分配连续内存 内存字节数=数组维数* sizeof(元素数据类型),数组名表示内存首地址, 是地址常量,一维数组,int a5= 2,4, 23,6,78 ;,二维数组的定义 定义方式: 数据类型 数组名常量表达式常量表达式;,数组元素的存放顺序 原因:内存是一维的 二维数组:按行序优先 多维数组:最右下标变化最快,例 int a34; float b25; int c234; int a3,4; (),行数,列数,元素个数=行数*列数,二维数组及多维数组,引用 例 aij ( i: 0N-1, j: 0M-1) 初始化,字符数组 定义:,初始化 逐个字符赋给数组中的元素; 利用字符串常量.,例 char c10, ch34;,字符串: 没有字符串变量,字符串用字符数组来处理 ; 一个字符串用 0作结束标志。 (或空字符),输入输出字符串 字符的输入/输出: %c 字符串的输入/输出: %s,例 使用 %c main() char str5; int i; for(i=0;i5;i+) scanf(“%c”, ,例 使用 %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+,strcmp(字符串1,字符串2) string.h 用字符的 ASCII 值逐个对应比较 字符串1 与 字符串2 字符的大小 (left-to-right); if 字符串1 字符串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) ,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,指针,指针变量,变量的内容,变量的地址,&与*运算符 含义,含义: 取变量的地址 单目运算符 结合性:自右向左,含义: 取指针所指向变量的内容 单目运算符 结合性:自右向左,两者关系:互为逆运算 理解,i_pointer-指针变量,它的内容是地址量 *i_pointer-指针的目标变量,它的内容是数据 &i_pointer-指针变量占用内存的地址,i_pointer &i &(*i_pointer) i *i_pointer *(&i),i_pointer = &i = &(*i_pointer) i = *i_pointer = *(&i),直接访问与间接访问 直接访问:按变量地址存取变量值 间接访问:通过存放变量地址的变量去访问变量,例 i=3; -直接访问,3,例 *i_pointer=20; -间接访问,20,例 k=i; -直接访问 k=*i_pointer; -间接访问,10,例 k=i; k=*i_pointer;,指针变量赋值(初始化),1通过取地址运算符( 它建立了如图所示的逻辑关系,因此当有语句: p=和scanf(%d,p)是等价的,2通过指针变量获得地址值 可以通过赋值运算,把一个指针变量中的地址值赋给另一个指针变量,从而使这两个指针变量指向同一地址 q=p; 使指针变量q中也存放了变量a的地址,也就是说指针变量p和q都指向了整型变量a 赋值号两边指针变量的基类型必须相同,3给指针变量赋“空”值 p=NULL; p=0; NULL的代码值为0, 应当注意: 1.指针变量只能存放地址,不能把一个整型量赋给指针变量 p=5; 应该通过取地址运算符“&”把一个地址赋给指针变量。 2.应避免使用没有赋值的指针变量,没有赋值的指针变量虽不会导致编译出错,但可能导致无法预料的灾难性后果,注意: ) 指针变量数据类型必须与所赋值的变量类型一致,例如以下语句是非法的。 float y; int *p; 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+的区别是什么?,数组元素表示方法, 变址运算符 ai *(a+i),ai pi *(p+i) *(a+i),数组名作函数参数 数组名作函数参数,是地址传递 数组名作函数参数,实参与形参的对应关系,字符串与数组关系 字符串用一维字符数组存放 字符数组具有一维数组的所有特点 数组名是指向数组首地址的地址常量 数组元素的引用方法可用指针法和下标法 数组名作函数参数是地址传递等 区别 存储格式:字符串结束标志 赋值方式与初始化 输入输出方式:%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个元素,a02 *(a0+2) *(*(a+0)+2),指向指针的指针 定义: 指向指针的指针 一级指针:指针变量中存放目标变量的地址,例 int *p1; int *p2; int i=3; p2=,二级指针:指针变量中存放一级指针变量的地址,例 int *p; int i=3; p=,一级指针,单级间接寻址,二级指针,一级指针,目标变量,二级间接寻址,定义形式:存储类型 数据类型 *指针名; 如 char *p;,例 int i, *p; p= ()/p是二级指针,不能用变量地址为其赋值,指针本身的存储类型,最终目标变量的数据类型,*p是p间接指向对象的地址 *p是p间接指向对象的值,例 int i=3; int *p1; int *p2; p1=,多级指针,例 三级指针 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); ,指向函数的指针 函数指针:函数在编译时被分配的入口地址,用函数名表示,函数指针变量赋值:如p=max;,函数返回值的数据类型,专门存放函数入口地址 可指向返回值类型相同的不同函数,指向函数的指针变量 定义形式: 数据类型 (*指针变量名)(); 如 int (*p)();,函数指针变量指向的函数必须有函数说明,函数调用形式: c=max(a,b); c=(*p)(a,b); c=p (a,b); 对函数指针变量pn, 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);,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=a; 试说明*(p+)与*(+p)有什么区别?,*(p+)是先取*p的值,后使p加1,对本例即先得到a0的值,然后p指针指向a1; *(+p)使先使p加1,后取*p的值, 对本例即p指针指向a1,再得到a1的值。,简答题,main( ) int x23=4,7,2,5,6,1; char *str =“thank“,“right“,“good“; char *p; int i,j; printf(“%d,%dn“,*x0,*(x1+2)/3); for(i=0;i2;i+) for(j=0;j3;j+) printf(“%d,“,*(xi+j); p=str; printf(“%c,%sn“,*(*p+1),*(p+2); ,4, 0,4,7,2,5,6,1,h, good,求程序运行输出结果,#include main() int a34=1,2,3,4,5,6,7,8,9,10,11,12; int (*p)4,i=2,j=1; p=a; printf(“%d,%d,”,*(*(p+i)+j),*(*(a+i)+j); printf(“%d,%dn”, *p,*(p+i); ,10,10,1,9,求程序运行输出结果,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!