当前位置:高等教育资讯网  >  中国高校课件下载中心  >  大学文库  >  浏览文档

《C语言教程》课程教学资源(教案讲义)第十章 指针

资源类别:文库,文档格式:DOC,文档页数:12,文件大小:164.5KB,团购合买
第十章指针 本章重点: 一、指针变量和指针运算符。 二、 指针用作函数参数。 三、指针与数组。
点击下载完整版文档(DOC)

第十章指针 本章重点 指针变量和指针运算符 指针用作函数参数 指针与数组。 10.1指针的基本概念 地址 在计算机中,把内存区划分为一个一个的存储单元,每个单元为 个字节(8位),它们都有一个编号,这个编号就是内存地址。如 下图所示: 低地址 C个字节 6543210 2002 2003 2004 高地址 注意:1、程序中定乂的每个数据在编译后都占有各自的内存区 2、数据所占有的存储单元个数是由其类型决定的。 3、首地址:第1个单元的地址, 4、表示地址的数与整数的区别: 5、系统通过变量名对内存单元进行访问 2.数据在内存中的存储 整型变量-分配2个字节单元 实型变量一分配4个字节单元 字符变量—分配1个字节单元

第十章 指针 本章重点: 指针变量和指针运算符。 指针用作函数参数。 指针与数组。 10.1 指针的基本概念 一、地址 在计算机中,把内存区划分为一个一个的存储单元,每个单元为 一个字节(8位),它们都有一个编号,这个编号就是内存地址。如 下图所示: 注意:1、程序中定义的每个数据在编译后都占有各自的内存区。 2、数据所占有的存储单元个数是由其类型决定的。 3、首地址:第 1 个单元的地址, 4、表示地址的数与整数的区别: 5、系统通过变量名对内存单元进行访问 2.数据在内存中的存储 整型变量---分配 2 个字节单元 实型变量—分配 4 个字节单元 字符变量—分配 1 个字节单元

例: kh 2000H 2001H3 变量 2002H 2003H 4 j变量 2006H 2007H 2.内存单元的地址与内存单元的内容 printf( %od, 1) scanf( %od, &i) 的操作过程。 3.对变量值的访问方式 (1)直接访问:按变量地址存取变量值的方式。 (2)间接访问方式:将变量的地址存放在另一个变量当中,通过 对另一变量来访问变量。 4.指针:就是变量的地址 指针变量:用于存放变量地址的变量 102指针变量和指针运算符 指针变量的定义 1.格式:类型名*指针变量名; 2、举例 int pI float *al. *a2. f: 3、说明 类型名:指针变量所指向的变量类型 b.*”是定义指针变量的标志,不可丢掉 c.指针变量定义后,其值是不确定的。 赋值:可以进行初始化,也可以使用赋值语句 (1)、初始化: *s=&a

2.内存单元的地址与内存单元的内容。 printf(“%d”,i); scanf(“%d”,&i); 的操作过程。 3.对变量值的访问方式 (1)直接访问:按变量地址存取变量值的方式。 (2)间接访问方式:将变量的地址存放在另一个变量当中,通过 对另一变量来访问变量。 4.指针:就是变量的地址。 指针变量:用于存放变量地址的变量。 10.2 指针变量和指针运算符 一.指针变量的定义 1. 格式:类型名 *指针变量名; 2、举例 int *p1; char *s1, *s2; float *a1, *a2, f; 3、说明 a. 类型名:指针变量所指向的变量类型。 b. “*” 是定义指针变量的标志,不可丢掉。 c. 指针变量定义后,其值是不确定的。 4、赋值:可以进行初始化,也可以使用赋值语句 (1)、初始化: int a, *s=&a;

(2)、赋值语句 =& 3)、注意:只能用同类型变量的地址进行赋值! 如定义:int*s; float f,则s=&f;是非法的。 二.指针变量的引用 1、两个运算符:&与* &:取地址,注意与作位运算符时的不同(双目) :取内容,注意与作乘运算符时的不同(双目) 说明 &既可作用于一般变量,也可作用于指针变量 *只能作用于指针变量 c.定义指针变量时的*与该处的含义不同 3、指针变量可以进行的操作 (1)赋值:inta,*pl=ka,*p2; 2=p1 下面的赋值是不合法的 int * ip ip=100 假设 int j=200x Int Ip &1 通过指针变量p间接访问变量 (2)输出: printi(%xpl1), (3)增减:pl+;p2-;p1+=4;(只能和一个整数) 不论指针变量指向何种数据类型,指针和整数进行加、减运 算时,编译程序总根据所指对象的数据长度对n放大。 (4).两个指针变量在一定条件下,可进行 减法运算。设p,q指向同一数组,则pq的绝对 值表示p所指对象与q所指对象之间的元素个 数 P a 例1 #include &al 11 main( int al=ll a2=22 int *pI, p2; 2 2 2 *p2

(2)、赋值语句 int a, *s; s=&a; 3)、注意:只能用同类型变量的地址进行赋值! 如定义:int *s; float f; 则 s=&f;是非法的。 二. 指针变量的引用 1、两个运算符:& 与 * &:取地址,注意与作位运算符时的不同(双目) *:取内容 ,注意与作乘运算符时的不同(双目) 2、说明 a. &既可作用于一般变量,也可作用于指针变量 b. * 只能作用于指针变量 c. 定义指针变量时的 * 与该处的含义不同 3、指针变量可以进行的操作 (1)赋值:int a, *p1=&a, *p2; p2=p1; 下面的赋值是不合法的: int *ip; ip=100; 假设: int i=200, x; int *ip; ip=&i; x=*ip; 通过指针变量 ip 间接访问变量 i, (2)输出:printf(“%x”,p1); (3)增减:p1++; p2--; p1+=4; (只能和一个整数) p+n 不论指针变量指向何种数据类型, 指针和整数进行加、减运 算时, 编译程序总根据所指对象的数据长度对 n 放大。 (4). 两个指针变量在一定条件下, 可进行 减法运算。设 p, q 指向同一数组, 则 p-q 的绝对 值表示 p 所指对象与 q 所指对象之间的元素个 数。 例 1 #include main( ) { int a1=11, a2=22; int *p1, *p2;

1=& 2=&a2 printf( %od, %,pl, p2) p2-p1; printf( %od, %dn'*pl, *p2); 例2 #include a main( a t al=lla2 int *pl, "p2, p pl=&al 2 p printf( % od, %dn, pl, p2); printf( %od, %dn,*pl, 'p2) 2 例3 #include *p1 maino int al=lla2=22.t &al It *pl, p2 p printf( %od, %dn, al, a2); a2 t=*p1;*pl=*p2;*p2气t printf( %/od, %dn al, a2); &a2 三、指针作为函数的参数 1、形式:只需要形式参数名前加上一个*即可。 tn: void test(int *pointer, char f, char*s) 2、说明

p1=&a1; p2=&a2; printf(“%d,%d\n”,*p1,*p2); p2=p1; printf(“%d,%d\n”,*p1,*p2); } 例 2 #include main( ) { int a1=11,a2=22; int *p1,*p2,*p; p1=&a1; p2=&a2; printf(“%d,%d\n”,*p1,*p2); p=p1; p1=p2; p2=p; printf(“%d,%d\n”,*p1,*p2); } 例 3 #include main( ) { int a1=11,a2=22,t; int *p1,*p2; p1=&a1; p2=&a2; printf(“%d,%d\n”,a1,a2); t=*p1; *p1=*p2; *p2=t; printf(“%d,%d\n”,a1,a2); } 三、指针作为函数的参数 1、形式:只需要形式参数名前加上一个*即可。 如:void test(int *pointer, char f, char *s) 2、说明

指针作为参数可以改变主调函数中变量的值 例4:对输入的两个整数按大小顺序输出 Void Swap(int pl, int p2) i int temp p=*pl; pl=*p2, *p2=temp; 1 Void maino f int a, b I, pointer 2 scanf(%d,9%d”,&a&b) pointer 1=&a, pointer 2=&b, if (ab)swap(pointer l, pointer 2); printf("n%d,%dn”,ab); 10.3指针与一维数组( Pointer and Arrays) 通过指针访问一维数组 数组结构的分析 设有数组定义为:inta5];则有: (1)a表示数组在内存中的首地址,也就是数组中第1 个元素的首地址,它是一个地址常量,其值由系 统在编译时确定,程序运行期间不能改变。 (2)数组中的各元素表示为: a0]、a[、a[2]、a[3]、a[4 或者是: (a+0)(或*a)、*a+1)、*(a+2)、*a+3)、*a+4) (3)数组中的各元素的地址表示为 &a[0]、&a[l、&a[2]、&a[3]、&a[4] 或者是:a+0(或a)、a 2、a+3 (4)另一种解释:数组名是基地址,下标是偏移量,a就表示以a 为基地址,偏移i个元素的那个元素 (5)数组的逻辑结构如下 &a[0]&a[1]&a[2]&a[3]&a[4] ]a[l]al2]a[3]a[4] 2、指针与数组的关系 现定义一个指针变量:int*p 并进行赋值:p=a,或p=&a[0

指针作为参数可以改变主调函数中变量的值。 例 4:对输入的两个整数按大小顺序输出 Void Swap( int *p1,int *p2) { int temp; temp=*p1; *p1=*p2; *p2=temp; } Void main() { int a,b; int *pointer_1,*pointer_2; scanf(“%d,%d”,&a,&b); pointer_1=&a; pointer_2=&b; if (a<b) swap(pointer_1,pointer_2); printf(“\n %d,%d\n”,a,b); } 10.3 指针与一维数组 (Pointer and Arrays) 一、通过指针访问一维数组 1、数组结构的分析 设有数组定义为:int a[5]; 则有: (1) a 表示数组在内存中的首地址,也就是数组中第 1 个元素的首地址,它是一个地址常量,其值由系 统在编译时确定,程序运行期间不能改变。 (2) 数组中的各元素表示为: a[0]、a[1]、a[2]、a[3]、a[4] 或者是: *(a+0)(或*a)、*(a+1)、*(a+2)、*(a+3)、*(a+4) (3) 数组中的各元素的地址表示为: &a[0]、&a[1]、&a[2]、&a[3]、&a[4] 或者是:a+0(或 a)、a+1、a+2、a+3、a+4 (4) 另一种解释:数组名是基地址,下标是偏移量,a[i]就表示以 a 为基地址,偏移 i 个元素的那个元素。 (5) 数组的逻辑结构如下: 2、指针与数组的关系 现定义一个指针变量:int *p; 并进行赋值:p=a; 或 p=&a[0];

则,指针变量p指向了数组a的开始,二者产生了联系,这样 就可以通过指针变量p访问数组a了 注意:a是指针常量,p是指针变量。 &a[0&a[1&a[2]&a[3]&a[4 a []a[2]a]a[4 (1)p+i和ai均表示a[的地址, (2)*(p+和+a+i)都表示p+i和a+所指对象的内容,即为a[。 (3)指向数组元素的指针,也可以表示成数组的形式,也就是 说,它允许指针变量带下标,如p回与*p+)等价 假若: 则p2]就相当于*(p+2),由于p指向a[5],所以p2]就相当于 a[7]。而p-3就相当于*(p-3),它表示a[2]。 3、一维数组的访问 例5用多种方法访问一维数组各元素 #include main( {inta[5}={1,3,5,7,9},i,*p=a for(i=0; 1<5; 1++)printf(%d, a[i) for(i=0; i<5; i++)printf("%od, (a+i)) for(i=0; 1<5; i++)printf( %d,piD; for(i=0; 1<5; 1++)printf("%od, " (p+i)) for G p<a+5 p++)printf( %d, p); p=a while(p<a+5)printf(" %od,p++) 4、几个表达式的分析P191 设定义:inta[3}={1,2,3},*s=a; (1) (2)s++,*s++ ++.*a++ (3)*(s++),(*s)++ (a++),(*a)++ (4)初始化时的*s=a;与语句*s=a;的不同 (5)一个指针变量加/减一个整数后,指针变量值的变化情况

则,指针变量 p 指向了数组 a 的开始,二者产生了联系,这样 就可以通过指针变量 p 访问数组 a 了。 注意:a 是指针常量,p 是指针变量。 (1). p+i 和 a+i 均表示 a[i]的地址, (2). *(p+i)和*(a+i)都表示p+i 和a+i 所指对象的内容, 即为a[i]。 (3). 指向数组元素的指针, 也可以表示成数组的形式, 也就是 说, 它允许指针变量带下标, 如 p[i]与*(p+i)等价。 假若: p=a+5; 则 p[2]就相当于*(p+2), 由于 p 指向 a[5], 所以 p[2]就相当于 a[7]。而 p[-3]就相当于*(p-3), 它表示 a[2]。 3、一维数组的访问 例 5 用多种方法访问一维数组各元素 #include main( ) { int a[5]={1, 3, 5, 7, 9}, i , *p=a; for (i=0;i<5;i++) printf(“%d”,a[i]); for (i=0;i<5;i++) printf(“%d”,*(a+i)); for (i=0;i<5;i++) printf(“%d”,p[i]); for (i=0;i<5;i++) printf(“%d”,*(p+i)); for (;p<a+5;p++) printf(“%d”,*p); p=a; while (p<a+5) printf(“%d”,*p++); } 4、几个表达式的分析 P191 设定义:int a[3]={1, 2, 3}, *s=a; (1)s, *s a, *a (2)s++, *s++, a++, *a++ (3)*(s++), (*s)++ *(a++), (*a)++ (4)初始化时的*s=a; 与语句 *s=a; 的不同 (5)一个指针变量加/减一个整数后,指针变量值的变化情况

10.2指针与多维数组 二维数组元素的地址 为了说明问题,我们定义以下二维数组 inta][4}={{0,132,3},{4,5,6,7},{8,9,10,11}; a[0] l0|1|2|3 a[] 4|5|67 l8|9|10|11 图 但从二维数组的角度来看,a代表二维数组的首地址,则 有: aB]4] (1000)→|0|112|3 4|5|6|7 (1016)}→|8|9|10|11 图6 二.指向多维数组的指针变量 1.在 Turbo C中,可定义如下的指针变量 inta[3][4l,(*p)4] 2.含义:pa是指针变量,它指向一个数组,数组 含有4个元素,每个元素的类型是int 3.说明 a.与定义int*pa;以及int*pa[4]含义不同。 b.如果执行pa++,则pa实际增加了多少呢? 开始时p指向二维数组第0行,当进行p+1运算时,根据地址运 算规则,此时放大因子为4x2=8,所以此时正好指向二维数组的第1 行。和二维数组元素地址计算的规则一样,*+1指向a[oJ1l,*(p+i)+j 则指向数组元素a 例6:有一个班,3个学生,各学4门课,计算总平均成绩,以 及第n个学生的成绩

10.2 指针与多维数组 一. 二维数组元素的地址 为了说明问题, 我们定义以下二维数组: int a[3][4]={{0,1,2,3}, {4,5,6,7}, {8,9,10,11}}; ┏━━━━┓ ┏━┳━┳━┳━┓ a─→ ┃ a[0] ┃─→┃0 ┃1 ┃2 ┃3 ┃ ┣━━━━┫ ┣━╋━╋━╋━┫ ┃ a[1] ┃─→┃4 ┃5 ┃6 ┃7 ┃ ┣━━━━┫ ┣━╋━╋━╋━┫ ┃ a[2] ┃─→┃8 ┃9 ┃10┃11┃ ┗━━━━┛ ┗━┻━┻━┻━┛ 图 5. 但从二维数组的角度来看, a 代表二维数组的首地址, 则 有: a[3][4] a ┏━┳━┳━┳━┓ (1000)─→ ┃0 ┃1 ┃2 ┃3 ┃ a+1 ┣━╋━╋━╋━┫ (1008)─→ ┃4 ┃5 ┃6 ┃7 ┃ a+2 ┣━╋━╋━╋━┫ (1016)─→ ┃8 ┃9 ┃10┃11┃ ┗━┻━┻━┻━┛ 图 6. 二. 指向多维数组的指针变量 1.在 Turbo C 中, 可定义如下的指针变量: int a[3][4], (*p)[4]; p=a; 2 .含义:pa 是指针变量,它指向一个数组,数组 含有 4 个元素,每个元素的类型是 int。 3.说明: a. 与定义 int *pa; 以及 int *pa[4]; 含义不同。 b. 如果执行 pa++,则 pa 实际增加了多少呢? 开始时p 指向二维数组第 0 行, 当进行 p+1 运算时, 根据地址运 算规则, 此时放大因子为 4x2=8, 所以此时正好指向二维数组的第 1 行。和二维数组元素地址计算的规则一样, *p+1 指向 a[0][1], *(p+i)+j 则指向数组元素 a[i][j]。 例 6: 有一个班,3个学生,各学4门课,计算总平均成绩,以 及第 n 个学生的成绩

Void maino Void average( float*p, int n) Void search(float(p)4],intn Float score[3[4}={65,67,70,60},{80,9790,81},{90,99,100,98} 12); Search(score, 2) Void average(float p, intn) i float p end Float sum=0.aver P end=p+n-1 for (p<p end; p++) sum=sum+(p); printf( average=%5.2fn', aver))) Void search(float(p)l4, intn For(i=0;1<4;1++ printf(%05.2,*(*(p+n+1) }∥/*p+n)表示一维数组的开始 10.3指针与字符串 1字符串还可以定义为:char*s= abcde”,它在内存中占用6个 字节,长度为5。其结构为: [0]s[1]s[2]s[3]s[4s[S c d 结束标志 2、用字符数组与用指针使用字符串的比较 定义及初始化 char s[= abcde’; char*p= abcde” 赋值 char s[6]; har"p s=abde”,/*不对,应为*/p=“ abcde”/把字符串首地址赋给p* strcpy (s, abcde) strcpy(p, abcde) 使用

Void main() { Void average( float * p,int n); Void search(float (*p)[4],int n); Float score[3][4]={{65,67,70,60},{80,97,90,81},{90,99,100,98}}; Average(score,12); Search(score,2); } Void average(float *p,int n) { float *p_end; Float sum=0,aver; P_end=p+n-1; for (;p<p_end;p++) sum=sum+(*p); aver=sum/n; printf(“average=%5.2f\n”,aver)}} Void search (float (*p)[4],int n) { int I; For (i=0;i<4;I++) printf(“%5.2f”,*(*(p+n)+i)); }// *(p+n)表示一维数组的开始 10.3 指针与字符串 1.字符串还可以定义为:char *s=“abcde”; 它在内存中占用 6 个 字节,长度为 5。其结构为: 2、用字符数组与用指针使用字符串的比较 • 定义及初始化 char s[]=“abcde”; char *p=“abcde”; • 赋值 char s[6]; char *p; s=“abcde”; /* 不对,应为 */ p=“abcde”;/*把字符串首地址赋给 p */ strcpy(s, “abcde”); strcpy(p, “abcde”); • 使用

s不能加减 p可以加/减 注意: char s[=“abc”,与 char sl={a',b’,c};的区别 例7.将字符数组a中的字符串拷贝到字符数组b中 该功能相当于 strep( a) (1)下标法 (2)指针法 include nano naimo char al="Hello, world! ", b20] char al="Hello, world!", b20: int 1: ch for(i=0;[!=“0’;i++) for①pa=a:pb=b;pa!=“0’;pa++,pb++) b=an b pb=“0’; pt(Qs”,b); po0s”,b); 3、通过指针在函数间传递字符串 ①、函数的定义形式 例如: char func(char a[, char bD 函数体;} 也可以写为: char func(char a, char *b) 函数体;} 例8设计一函数,实现与标准函数 strcpy类似的功能 #include Did mystrcpy (char *to, char *from); main( i char ca[20],*cp=Hello, world! mystrcpy(ca, cp); A printf( %s",ca) void mystrcpy(char *to, char * from)

s 不能加/减 p 可以加/减 注意:char s[]=“abc”;与 char s[]={‘a’,’b’,’c’};的区别 例 7. 将字符数组 a 中的字符串拷贝到字符数组 b 中 3、通过指针在函数间传递字符串 ①、函数的定义形式 例如: char func(char a[], char b[]) { 函数体;} 也可以写为: char func(char *a, char *b) { 函数体;} 例 8 设计一函数,实现与标准函数 strcpy 类似的功能。 #include void mystrcpy(char *to, char *from); main( ) { char ca[20], *cp=“Hello,world!”; mystrcpy(ca,cp); printf(“%s”,ca); } void mystrcpy(char *to, char *from) {

while *from!=0*to=*from; to++, from++ *tO=0 思考:调用 mystery(ca,cp+2),结果如何? 104指针数组与指向指针的指针 、指针数组 1、指针数组的概念 指针数组是一种特殊的数组,它每个元素的类型都是指针类型(即 地址),其它与一般数组相同。 当把某个量的地址放入某元素中后,即可通过该元素对相应的量 进行间接访问 指针数组的定义 类型名*指针数组名[常量表达式];∥其中比*优先级高 如:int*ap[3 char*s[0];等等。 !!请回忆:二维数组:int(*p)4,区别异同? 3、指针数组的初始化 (1) int al15,a2[5],a3[5],*ap[3}={al,a2,a3} (2)char*sp={abc,“123”,Helo”}; 4、指针数组的赋值 上面的情况中,可以先定义变量,在进行赋值,即 (1) int al[5],a2[5l,a3[5,*ap[3] [OF=al; apll=a2; ap 2] (2)char*sp={abc”,123”, Hello} sp[oFabc', sp[1=123, sp[2=Hello 例9:打印1月至12月的月名 har*month name(intn) static char *named=i Illegal month" January "February, "March april Ma June July

while (*from!=‘\0’){ *to=*from; to++; from++; } *to=‘\0’; } 思考:调用 mystrcpy(ca,cp+2),结果如何? 10.4 指针数组与指向指针的指针 一、指针数组 1、指针数组的概念 指针数组是一种特殊的数组,它每个元素的类型都是指针类型(即 地址),其它与一般数组相同。 当把某个量的地址放入某元素中后,即可通过该元素对相应的量 进行间接访问。 2、指针数组的定义 类型名 *指针数组名[常量表达式];//其中[]比*优先级高 如:int *ap[3]; char *s[10]; 等等。 !! 请回忆:二维数组:int (*p)[4], 区别异同? 3、指针数组的初始化 (1)int a1[5], a2[5], a3[5], *ap[3]={a1, a2, a3}; (2)char *sp[]={“abc”, “123”, “Hello”}; 4、指针数组的赋值 上面的情况中,可以先定义变量,在进行赋值,即 (1)int a1[5], a2[5], a3[5], *ap[3]; ap[0]=a1; ap[1]=a2; ap[2]=a3; (2)char *sp[]={“abc”, “123”, “Hello”}; sp[0]=“abc”; sp[1]=“123”; sp[2]=“Hello”; 例 9: 打印 1 月至 12 月的月名: char *month_name(int n) { static char *name[]={ "Illegal month", "January", "February", "March", "April", "May", "June", "July

点击下载完整版文档(DOC)VIP每日下载上限内不扣除下载券和下载次数;
按次数下载不扣除下载券;
24小时内重复下载只扣除一次;
顺序:VIP每日次数-->可用次数-->下载券;
共12页,试读已结束,阅读完整版请下载
相关文档

关于我们|帮助中心|下载说明|相关软件|意见反馈|联系我们

Copyright © 2008-现在 cucdc.com 高等教育资讯网 版权所有