资源预览内容
第1页 / 共44页
第2页 / 共44页
第3页 / 共44页
第4页 / 共44页
第5页 / 共44页
第6页 / 共44页
第7页 / 共44页
第8页 / 共44页
第9页 / 共44页
第10页 / 共44页
亲,该文档总共44页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第11章 指针(一) Date1 主要内容 n指针是C语言中一个非常重要的概念 ,也是C语言中最具特色的内容 n正是有了指针,才使得C语言的功能 比其他语言强大 n指针是C语言的一种数据类型,这种 类型的变量存放的内容是地址数据 n重点:指针的概念、定义和简单使用 Date2 11.1 变量的指针与指针变量 n 在计算机中,存储器由字节组成,每个字节有一 个编号,编号是按自然顺序排列的,每个字节的 编号就是该字节的地址 n 数据存放在存储器的字节中,不同数据类型的数 据所占用的内存字节数不同 n 在TC编译系统中,整型量占2个字节,字符量占 1个字节等 n 根据一个内存单元的编号可以准确地找到该内存 单元,内存单元的编号也称为地址,通常也把这 个地址称为指针 Date3 变量的地址与内容 n当定义一个变量时,系统会根据变量的数 据类型为这个变量分配一定的存储单元( 连续的字节),这些字节的首地址就是这 个变量的地址(或指针) n在这些存储单元中可以存储数据,所存放 的数据是以二进制的形式表示的,称为变 量的内容 n内存单元的指针和内存单元的内容是两个 不同的概念 Date4 指针变量 n变量的地址是编号,也是数据,这种数据 表示的是地址,也是可以被存取的 n在语言中,允许用一个变量来存放指针 ,这种变量称为指针变量 n一个指针变量的值就是某个内存单元的指 针或某个内存单元的地址,称这个指针变 量指向该内存单元 Date5 变量和其指针变量的关系 n 变量x的内容为45,x占用 了021A号单元(地址用十 六进制数表示,由系统随 机分配) n 指针变量p,占用了022B 号单元,变量的内容为数 据021A,这正是变量x的 地址 n 称p指向变量x,或者说p 是指向变量x的指针 Date6 指针和指针变量 n指针和指针变量是不同的 n一个指针是一个地址,是一个 常量。而一个指针变量是变量 ,可以被赋予不同的指针值 n定义指针变量的目的是为了通 过指针变量去访问内存单元 n变量x的指针是021A,p是指 向变量x的指针变量 Date7 直接访问:按变量地址存取变量值 间接访问:将变量地址放在另一内存单元-指针变量中 先找到存放地址的单元地址,从中取出地址,再从该地 址取出变量值. 直接访问优点:简单方便 间接访问优点:无后顾之忧,如有多个人,可共享1把钥匙 直接访问与间接访问 Date8 存储的概念 n 在语言中,一种数据类型或数据结构往往都占 有一段连续的内存单元。例如,数组和函数。 n 指针变量的值表示的是一个地址,这个地址不仅 可以是某个变量的地址,也可以是其他数据结构 的地址 n 一个数组的首地址可以存放在一个指针变量中, 一个函数的首地址也可以存放在一个指针变量中 。数组和函数都是连续存放的,通过访问指针变 量可以取得数组或函数的首地址,找到该数组或 函数 n 通过指针变量可以使用数组或函数,程序会变得 精练、高效 Date9 11.2 指针变量的定义与引用 n定义一个指针变量的一般形式为 类类型说说明符 *变变量名; 如, int *p; float *p2,*q2; 1. 指针变量的定义 Date10 int *p; float *p2,*q2; n *表示这是一个指针变量,变量名即为定义的指 针变量名,类型说明符表示该指针变量所指向的 变量的数据类型,通常称为基类型 n p,p2,q2是三个指针变量。 n p的基类型是int,p的值只能是某个int类型变量 的地址,或者说p只能指向一个int类型的变量 n p2和q2的基类型是float,p2和q2的值是float类 型变量的地址,或者说p2和q2只能指向float类 型的变量 Date11 运算符“*”的含义 n 在程序中用“*”符号表示“指向”,表示指针变量和 它所指向的变量之间的关系。 n p代表指针变量,若p指向变量x,那么*p就是p所 指向的变量,也就是变量x。此时*p和x都表示x 的内容 Date12 变量的赋值 有了前面的定义,下面两个语句作用相同: x = 45; *p = 45; n 第一个语句的含义是把45赋给变量x,第二个语 句的含义是将45赋给指针变量p所指向的变量, 即变量x。 n 注意第二个语句不要写为 p = 45; Date13 2. 指针变量的引用 n指针变量同普通变量一样,使用之前不仅 要定义说明,而且必须赋予具体的值 n未经赋值的指针变量不能使用,否则将造 成系统混乱,甚至死机。因为此时系统不 知道指针变量的值是多少,也就是不知道 它指向哪里 n指针变量的赋值只能赋予地址,决不能赋 予其他数据,否则将引起错误 n在语言中,变量的地址是由编译系统分 配的 , 对程序员是透明的 Date14 “ int *p= 可以这样来看: “*p”是变量x,即x的内容 “ scanf(“%d,%d“, p1= p2= if(ab) p=p1; p1=p2; p2=p; printf(“na=%d,b=%dnn“,a,b); printf(“max=%d,min=%dn“,*p1,*p2); p1 5 a p2 9 b p a,b的值并未改变,只是 指针指向进行了改变 Date24 【例11.3】分析程序的运行结果 # include int main ( ) int a = 20, b = 10; int *p, *q; p = q = *p = *p + 10; printf ( “a = %d, b = %dn“, a, b ); printf ( “*p = %d, *q = %dn“, *p, *q ); printf ( “p = %x, q = %xn“, p, q ); printf ( “ b = *p; q = p; *q = *q + 20; printf ( “a = %d, b = %dn“, a, b ); printf ( “*p = %d, *q = %dn“, *p, *q ); printf ( “p = %x, q = %xn“, p, q ); printf ( “ return 0; Date25 指针变量作函数参数-重中之重 o 指针的历史作用:替代汇编语言,直接访问物理地址, 处理动态内存等。 o 指针灵活,但掌握困难,很容易出错(难以排错)。 o Java中指针的发展趋势:取消了指针,代替为引用。 q引用-“受限的指针” q指针的最重要作用:用作函数参数 Date26 11.3 指针变量应用举例 v经典例题:输入a,b,从大到小输出 指针的最经典例题之一,值得背诵的代码 Date27 main() int a,b; int *pointer_1,*pointer_2; scanf(“%d,%d“, pointer_1= pointer_2= if(ab) swap(pointer_1,pointer_2); printf(“n%d,%dn“,a,b); swap(int *p1,int *p2) int temp; temp=*p1; *p1=*p2; A *p2=temp; swap(int *p1,int *p2) int *temp; *temp=*p1; *p1=*p2; B *p2=*temp; swap(int x,int y) int temp; temp=x; x=y; C y=temp; swap(int *p1,int *p2) int *temp; temp=p1; p1=p2; D p2=temp; 四个不同的子函数,那些可以完成程序功能? 那些不能?为什么? Date28 第1个被否定的 swap(int x,int y) int temp; temp=x; x=y; C y=temp; main( ) int a,b; int *pointer_1,*pointer_2; scanf(“%d,%d“, pointer_1= pointer_2= if(ab) swap(pointer_1,pointer_2); printf(“n%d,%dn“,a,b); 原因1、函数实参和形参类型不一致。 原因2、函数参数传递为值传递。子函数中形参的改 动对主函数实参无影响。 Date29 mainswap a b x y temp 5 9 5 9 5 9 5 temp=x; x=y; y=temp; swap(a,b); 双黄线是堵墙 函数边界 Date30 第1个被肯定的 main() int a,b; int *pointer_1,*pointer_2; scanf(“%d,%d“, pointer_1= pointer_2= if(ab) swap(pointer_1,pointer_2); printf(“n%d,%dn“,a,b); swap(int *p1,int *p2) int temp; temp=*p1; *p1=*p2; A *p2=temp; 原因、通过指针方式透过了函数边界的限制;函数参 数传递方式为地址传递。 Date31 mainswap a b p1 p2 temp 5 9 *p1=*p2; *p2=temp; swap(pointer_1,pointer_2); int temp; p1,p2并不知道main函数中存在a,b变 量;但通过指针可以找到两个地址 Date32 第2个被否定的 main() int a,b; int *pointer_1,*pointer_2; scanf(“%d,%d“, pointer_1= pointer_2= if(ab) swap(pointer_1,pointer_2); printf(“n%d,%dn“,a,b); swap(int *p1,int *p2) int *temp; temp=p1; p1=p2; D p2=temp; 原因、虽然函数参数传递用了指针和地址传递方式,但 子函数中仅对指针进行了修改,未修改主函数的实参。 Date33 mainswap a b p1 p2 temp 5 9 p1=p2; p2=temp; swap(pointer_1,pointer_2); int *temp; Date34 能够成功但是必须否定的 main() int a,b; int *pointer_1,*pointer_2; scanf(“%d,%d“, pointer_1= pointer_2= if(ab) swap(pointer_1,pointer_2); printf(“n%d,%dn“,a,b); swap(int *p1,int *p2) int *temp; *temp=*p1; *p1=*p2; B *p2=*temp; 原因:指针使用很容易犯的错误之一,地址未初始化 而可能修改未知区域。 Date35 *temp=*p1; *p1=*p2; *p2=*temp; swap(pointer_1,pointer_2); int *temp; mainswap a b p1 p2 temp 5 9 *temp=*p1; 5 5 5 系统 整体内存 未使 用内 存 已使用内存,如 windows操作系统 系统崩溃 病毒 工作原理 Date37 未初始化的 隐藏错误 swap(int *p1,int *p2) int temp; temp=*p1; *p1=*p2; A *p2=temp; swap(int *p1,int *p2) int *temp; *temp=*p1; *p1=*p2; B *p2=*temp; swap(int x,int y) in
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号