ー十/∵_l∴∴二__二..十・...‡lll∴_三∴ー十/∵_l∴∴二__二..十・...‡lll∴_三∴ 社団法人 田本セラミックス協会 脅ラミッタス基礎王学講座小委員会
第十二章 指针
description
Transcript of 第十二章 指针
第十二章 指针
第十二章 指针
12.1 指针与指针变量 如: int a=1 , b=2 ; float x=3.4 , y = 4.5 ; double m=3.124 ; char ch1='a‘, ch2='b' ;
12
4.5
3.4
3.124
ab
20002002
2004
2008
2012
20202021
变量 a变量 b
变量 x
变量 y
变量 m
变量 ch1变量 ch2
一个地址唯一指向一个内存变量,我们称这个地址为变量的指针。如果将变量的地址保存在内存的特定区域,用变量来存放这些地址,这样的变量就是指针变量,通过指针对所指向变量的访问,也就是一种对变量的“间接访问”。
第十二章 指针
12
4.5
3.4
3.124
ab
20002002
2004
2008
2012
20202021
变量 a变量 b
变量 x
变量 y
变量 m
变量 ch1变量 ch2
1012
pa
1004
2012
2000200220042008
20202021
10001002
100610081010
10141016
pbpxpypm
pch1pch2
设一组指针变量 pa 、 pb 、 px 、 py 、 pm 、 pch1 、 pch2 ,分别指向上述的变量 a 、 b 、 x 、 y 、 m 、 ch1 、ch2 ,指针变量也同样被存放在内存,二者的关系如图:
12.1 指针与指针变量
第十二章 指针
指针定义的格式: 类型说明符 * 指针名; * 表示这是一个指针变量, 变量名即为定义的指针变量名; 类型说明符表示本指针变量所指向的变量的数据类型,也就是说一个指针变量只能指向同一类型的变量。 如: int *p1 ; 表示 p1 是一个指针变量,它的值是某个整型变量的地址。或者说 p1 指向一个整型变量。至于 p1 究竟指向哪一个整型变量,应由向 p1 赋予的地址来决定。
12.2 指针变量的定义与引用一、指针变量的定义
第十二章 指针
赋值形式: & 变量名; &:取地址符 &a 表示变量 a 的地址, &b 表示变量 b 的地址。变量本身必须预先说明。 指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体的值。未经赋值的指针变量不能使用,否则将造成系统混乱,甚至死机。 指针变量的赋值只能赋予地址,决不能赋予任何其它数据,否则将引起错误。
12.2 指针变量的定义与引用二、指针变量的赋值
第十二章 指针
设有指向整型变量的指针变量 p ,如要把整型变量 a 的地址赋予 p 可以有以下两种方式:1 )指针变量初始化的方法 int a ; int *p=&a ;2 )赋值语句的方法 int a ; int *p ; p=&a ; 不允许把一个数赋予指针变量,下面的赋值是错误的: int *p ; p=1000 ; 被赋值的指针变量前不能再加“ *” 说明符,如写为 *p=&a 也是错误的。
12.2 指针变量的定义与引用二、指针变量的赋值
第十二章 指针
指针变量只能进行赋值运算和部分算术运算及关系运算。(1) 取地址运算符 & :是单目运算符,其结合性为自右至左,其功能是取变量的地址。(2) 取内容运算符 * :是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在“ *” 运算符之后跟的变量必须是指针变量。 注意:在指针变量说明中,“ *” 是类型说明符,表示其后的变量是指针类型。而表达式中出现的“ *” 则是一个运算符用以表示指针变量所指的变量。
12.2 指针变量的定义与引用二、指针变量的运算
第十二章 指针
[ 例 12.1] 指针变量程序举例。。main( ){ int *p1 , *p2 , i1 , i2 ; scanf(“%d , %d” , &i1 , &i2) ; p1=&i1 ; p2=&i2 ; printf(“%d , %d\n” , *p1 , *p2) ; p2=p1 ; printf(“%d , %d\n” , *p1 , *p2) ;} 若输入: 3 , 5则输出: 3 , 5 3 , 3
12.2 指针变量的定义与引用二、指针变量的运算
第十二章 指针
[ 例 12.2] 从键盘输入两个整数,按由大到小的顺序输出。main( ){ int *p1 , *p2 , a , b , t ; scanf("%d , %d " , &a , &b) ; p1=&a ; p2=&b ; if(*p1<*p2) { t=*p1 ; *p1=*p2 ; *p2=t ; } printf("%d , %d\n" , a , b) ;}
12.2 指针变量的定义与引用二、指针变量的运算
第十二章 指针
使用指针类型做函数的参数,实际向函数传递的是变量的地址。由于函数中获得了所传递变量的地址,在该地址空间的数据当函数调用结束后被物理地保留下来。因此,如果希望函数间传递的是地址,实参用变量的地址或指针变量,形参用指针变量。
12.3 指针变量做函数的参数
第十二章 指针
[ 例 12.3] 利用指针变量作为函数的参数,用函数的方法再次实现上述功能。main ( ){ void change() ; int *p1,*p2,a,b,*t ; scanf("%d , %d" , &a , &b) ; p1=&a ; p2=&b ; change(p1 , p2) ; / * 函数调用 * / printf("%d , %d\n" , *p1 , *p2) ;}void change(int *pt1 , int *pt2){ int t ; if(*pt1<*pt2) { t=*pt1 ; *pt1=*pt2 ; *pt2=t ; } return ;}
12.3 指针变量做函数的参数
第十二章 指针
指向数组元素的指针变量的定义与指向变量的指针变量的定义相同 如: int a[10] ; int *p ; 对该指针元素赋值: p=&a[0] ; 把 a[0] 元素的地址赋给指针变量 p ,即 p 指向
a 数组的第 0 号元素, 数组名代表数组的首地址,也就是第一个元素的地址。因此, p=&a[0] ;与 p=a ;等价。
12.4 指针与数组一、指向数组元素的指针变量的定义与赋值
第十二章 指针
在定义指针变量时可以赋给初值: int *p=&a[0] ;它等效于: int *p ; p=&a[0] ; 定义时也可以写成: int *p=a ; 它的作用是将 a 的首地址(即 a[0] 的地址)赋给指针变量 p (而不是 *p )。
12.4 指针与数组一、指向数组元素的指针变量的定义与赋值
第十二章 指针
设 p 已定义为指针变量,并已给它赋了一个地址,使它指向某一个数组元素。如果有以下赋值语句: *p=1 ; 表示对 p 当前所指向的数组元素赋以一个值(值为 1 )。 C 规定 p + 1 指向数组的下一个元素 ( 而不是将 p 值简单地加 1) 。 如,数组元素是实型,每个元素占 4 个字节,则 p + 1意味着使 p 的原值(地址)加 4 个字节,以使它指向下一元素。 p + 1 所代表的地址值实际上是 p + 1d ,
d 是一个数组元素所占的字节数(对整型, d=2 ;对实型, d = 4 ;对字符型, d = 1 )。
12.4 指针与数组二、通过指针引用数组元素
第十二章 指针
如果 p 的初值为& a[0] ,则: (1) p + i 和 a + i 就是 a[i] 的地址,或者说,它们指向 a数组的第 i 个元素。(2) *(p + i) 或 *(a + i) 是 p + i 或 a + i 所指向的数组元素,即 a[i] 。 (3) 指向数组的指针变量也可以带下标,如 p[i] 与 *(p + i)等价。(4) 当指针指向一串连续的存储单元时,可以对指针进行加上或减去一个整数,这种操作称为指针的移动。 (5) 指针不允许进行乘、除运算,移动指针时,不允许加上或减去一个非整数,对指向同一串连续存储单元的两个指针只能进行相减操作。
12.4 指针与数组二、通过指针引用数组元素
第十二章 指针
[ 例 12.4] 从键盘输入 10 个整数,存放在数组中,并输出数组的全部元素。用指针变量指向数组元素。main( ) { int i , a[10] , *p ; for (i=0 ; i<10 ; i ++ ) scanf("%d" , &a[i]) ; for(p=a ; p<a + 10 ; p ++ ) printf("%4d" , *p) ; printf("\n") ;}
12.4 指针与数组二、通过指针引用数组元素
第十二章 指针
注意:(1) 用 p ++使 p 的值不断改变,这是合法的,如果不用 p 而企图使 a 变化是不行的,如将上述程序的最后两行改为: for(p=a ; a<p + 10 ; a ++ ) printf("%d" , *a) ;(2) 要注意指针变量的当前值,请看下面的程序。
12.4 指针与数组二、通过指针引用数组元素
第十二章 指针
[ 例 12.5] 输出 a 数组的 10 个元素。main ( ) { int *p , i , a[10] ; p=a ; for(i=0 ; i<10 ; i ++ ) scanf ("%d" , p ++ ) ; for(i=0 ; i<10 ; i ++ , p ++ ) printf ("%d" , *p) ; printf ("\n") ;}输入: 1 2 3 4 5 6 7 8 9 0<回车 >运行结果 :22153 234 0 0 30036 25202 11631 8259 8237 28483
12.4 指针与数组二、通过指针引用数组元素
解决这个问题的办法是在第二个 for循环改为如下形式:for(i=0 , p=a ; i<10 ; i ++, p ++ ) printf("%d" , *p) ;
第十二章 指针
(3) 注意指针变量的运算。如果先使 p 指向数组 a( 即 p=a),则:①p++( 或 p+=1) , p 指向下一元素 a[1] ,若再执行 *p ,取了元素 a[1] 的值。②*p++ ,由于 ++ 和 * 同优先级,是自右而左的结合方向,因此它等价于 *(p++) 。作用是先得到 p 指向的变量的值( 即 *p) ,然后再使 p+1 。③* ( p++ )和 *++p 作用不同。前者是先取 *p 值。然后使 p移动,后者是先使 p移动,再取 *p 。若 p 的初值为 a (即& a[0] ),输出 * ( p++ )时,得 a[0] 的值,而输出 * ( ++p ),则得到 a[1] 的值。
12.4 指针与数组二、通过指针引用数组元素
第十二章 指针
④(*p)++ 表示 p 所指向元素值加 1 ,即 (a[0])++ ,如果 a[0]=3 ,则执行 (a[0])++ 后, a[0] 的值为4 。注意,是元素值加 1 ,而不是指针值加 1 。⑤如果当前 p 指向 a 数组中第 i 个元素,则:
*(p--) 相当于 a[i--] ,先取 p 值作“ *” 运算,再使 p 自减。 *(++p) 相当于 a[++i] ,先使 p 自加,再作 * 运算。 *(--p) 相当于 a[--i] ,先使 p 自减,再作 * 运算。
12.4 指针与数组二、通过指针引用数组元素
第十二章 指针
数组名可以用作函数的实参传给形参。由于数组名是一个地址值,对应的形参就应该是数组名或一个指针变量,但该指针必须与数组类型一致。
12.4 指针与数组三、数组名做函数参数
main ( ) f(int *arr) { int array[10] { …… …… f(array) } …… }
如:
第十二章 指针
数组名作为实参时,对应的函数首部可以写成如下三种形式: ①f( int *arr ) ②f( int arr[10] ) ③f( int arr[ ])
12.4 指针与数组三、数组名做函数参数
第十二章 指针
[ 例 12.6] 有一个一维数组 score ,内存放 10 个学生成绩,求平均成绩。float average(float * array){ int i ; float aver , sum=0 ; for (i=0 ; i<10 ; i ++ ) sum=sum + array[i] ; aver=sum/10 ; return (aver) ;}main ( ){ float score[10] , ave ; int i ; printf ("Input 10 scores : \n") ; for (i=0 ; i<10 ; i ++ ) scanf("%f" , &score[i]) ; printf (“\n”) ; ave=average (score) ; printf ("Average score is %5.1f" , ave) ;}运行情况如下: Input 10 scores: 100 56 78 98.5 76 87 99 67.5
75 97<回车 >运行结果: Average score is 83.40
12.4 指针与数组三、数组名做函数参数
第十二章 指针
[ 例 12.7] 有程序如下:float average (float *array , int n){ int i ; float aver , sum=0 ; for(i=0 ; i<n ; i ++ ) sum=sum + array[i] ; aver=sum/n ; return (aver) ; }main ( ){ float score_1[5]={98.5,97,91.5,60,55} ; float score _2[10]={67.5,89.5,99,69.5,77,89.5,76.5,54,60,9
9.5}; printf ("A- average : %6.2f\n“,average (score_1,5)) ; printf ("B―average : %6.2f\n“,average (score_2,10)) ;}运行结果如下: A- average : 80.40 B- average : 78.20
12.4 指针与数组三、数组名做函数参数
第十二章 指针
[ 例 12.8] 定义长度为 10 的整型类型一维数组,并将数组中的元素按逆序存放后输出其值 (完成逆序存放操作时,只允许开辟一个临时存储单元 ) 。 main ( ){ int i , a[10] ; for(i=0 ; i<10 ; i ++ ) scanf("%d" , &a[i]) ; for(i=0 ; i<10 ; i ++ ) printf("%4d" , a[i]) ; printf(“\n”) ; fun(a , 10) ; for(i=0 ; i<10 ; i ++ )printf("%4d" , a[i]) ; printf("\n") ;}fun(int *a , int n){ int i , j , t ; for(i=0 , j=n- 1 ; i<j ; i ++, j-- ) { t=a[i] ; a[i]=a[j] ; a=[j]=t ; }}
12.4 指针与数组三、数组名做函数参数
第十二章 指针
[ 例 12.9] 已知一维数组中存放互不相同的 10 个整数,从键盘输入一个数,从数组中删除与该值相同的元素中的值。main ( ){ int i,t,a [10]={2,4,1,6,5,9,7,0,8,3} ; for(i=0 ; i<10 ; i ++ ) printf("%4d" , a[i]) ; printf(“\nlnput t:\n”) ; scanf("%d" , &t) ; del(a , t) ; for(i=0 ; i<9 ; i ++ ) printf("%4d" , a[i]) ; printf("\n") ;}del(int a[10] , int t ){ int i , j ; for(i=0 ; i<10 ; i ++ ) if(t== a[i]) break ; for(j=i ; j<9 ; j ++ ) a[j]=a[j + 1] ;}
12.4 指针与数组三、数组名做函数参数
第十二章 指针
[ 例 12.10] 用选择法对 10 个整数按由小到大顺序排列。main( ){ int i , a[10] ; for(i=0 ; i<10 ; i ++ ) scanf(“%d” , &a[i]) ; sort(a , 10) ; for(i=0 ; i<10 ; i ++ ) printf(“%d” , a[i]) ; printf("\n") ;} sort (int p[ ] , int n) { int i , j , k , temp ; for(i=0 ; i<n- 1 ; i ++ ) { k=i ; for(j=k + 1 ; j<n ; j ++ ) if(p[j]<p[k]) k=j ; temp=p[i] ; p[i]=p[k] ; p[k]=temp ; }}
12.4 指针与数组三、数组名做函数参数
第十二章 指针
[ 例 12.11]假定 a 数组中已存放由小到大顺序排序的 10 个数,在 a 数组中插入一个数,插入后数组中的数仍有序。main ( ){ int I,x,a [11]={1,3,5,7,9,11,13,15,17,19} ; printf(“Input x : \n”) ; scanf("%d" , &x) ; for(i=0 ; i<10 ; i ++ ) printf ("%4d" , a[i]) ; printf(“\n”) ; insert(a , x) ; for(i=0 ; i<11 ; i ++ ) printf ("%4d" , a[i]) ; printf("\n") ;}insert(int *a , int x){ int i,j ; i=0 ; while(i<10 &&a[i]<x) i ++; for(j=9 ; j>=i ; j――) a[j + 1]=a[j] ; a[i]=x ;}
12.4 指针与数组三、数组名做函数参数
第十二章 指针
[ 例 12.12]求一维数组中值最大的那个元素的值,以及其所在的位置。main ( ){ int i , k , max ; int a[10]={3,4,9,1,7,6,- 10,10,- 5,
2} ; for(i=0 ; i<10 ; i ++ ) printf("%d" , a[i]) ; printf(“\n”) ; max=find(a , &k) ; printf("max=%d , k=%d\n" , max , k) ;}find(int a[10] , int *k){ int i , max ; max=a[0] ; *k=0 ; for(i=0 ; i<10 ; i ++ ) if(max<a[i]) { max=a[i] ; *k=i ; } return max ; }
12.4 指针与数组三、数组名做函数参数
第十二章 指针
设已定义二维数组 a : int a[3][4]={{1,3,5,7},{9,11,13,15,15},{17,19,21,23}};( 1 ) a 是二维数组名,是二维数组的起始地址 ( 设地址为 200
0) 。即, a 指向 a 数组第 0 行, a 也是 0 行首地址。( 2 ) a + 1 是 a 数组第 1 行首地址,或者说 a + 1 指向第 1 行(地址为 2008 )。( 3 ) a[0],a[1],a[2] 是二维数组中三个一维数组(即三行)的名字,因此它们也是地址 ( 分别是 0 行, 1 行, 2 行的首地址 ) 。 ( 4 ) a[i]+j 是 i 行 j列元素的地址, *(a[i]+j) 是 i 行 j列元素的值。 ( 5 ) a[i] 与 *(a + i)无条件等价,这两种写法可以互换。
12.4 指针与数组四、指向多维数组的指针和指针变量
第十二章 指针
( 6 ) a[i][j] , *(a[i] + j) , *(*(a + i) + j)都是i 行 j列元素的值。( 7 )区别行指针与列指针的概念。例如 a + 1 和a[1]都代表地址 2008 。但 a + 1 是行指针。它指向一个一维数组。 a[1]( 即 *(a + 1)) 是列指针,它指向一个元素,它是 1 行 0列元素的地址。( 8 )可以定义指向一维数组的指针变量, 如: int (*p)[4] ; /* 称 p 为行指针 */ 定义 p 为指向一个含 4 个元素的一维数组的指针变量。
12.4 指针与数组四、指向多维数组的指针和指针变量
第十二章 指针
main ( ){ int a[3][4] ; int * p1 , (*p2)[4] ; p1=&a[3][4] ; /*p1 是列指针 */ p2=a + 1 ; /*p2 是行指针 */}不能写成:p1=a + 1 ; p2=&a[3][4] ; /* 类型不一致 */
12.4 指针与数组四、指向多维数组的指针和指针变量
第十二章 指针
12.5 字符串的指针和指向字符串的指针变量一、字符串的表示形式 可以用两种方法实现一个字符串:1. 用字符数组实现[ 例 12.13] 用字符数组实现的示例。main ( ) { char string [ ]= " I love China! " ; printf("%s\n" , string) ;}string 是数组名,它代表字符数组的首地址
第十二章 指针
2. 用字符指针实现可以不定义数组,而定义一个字符指针。用字符指针指向字符串中的字符。[ 例 12.14] 用字符指针实现的示例。main ( ){ char *string= " I love China! " ; printf("%s\n" , string) ;}注意:在内存中,字符串的最后被自动加了一个‘ \0’ ,因此在输出时能确定字符串的终止位置。通过字符数组名或字符指针变量可以输出一个字符串,而对一个数值型数组,是不能企图用数组输出它的全部元素的,只能逐个元素输出。
12.5 字符串的指针和指向字符串的指针变量一、字符串的表示形式
第十二章 指针
[ 例 12.15] 将字符串 a复制到字符串 b (用指针变量来处理)。main ( ){ char a[ ] = "I am a boy. " , b[20] , *p1 , *p2 ; int i ; for(p1=a , p2=b ; *p1!= '\0' ; p1 ++, p2 ++ ) *p2=*p1 ; /* 只复制有效字符 */ *p2='\0' ; /* 赋字符串结果标志 */ printf ("String a is : %s\n" , a) ; printf ("String b is : %s\n" , b) ;}
12.5 字符串的指针和指向字符串的指针变量一、字符串的表示形式
第十二章 指针
字符数组与字符指针变量的区别:( 1 )字符数组由若干个元素组成,每个元素存放一个字符,而字符指针变量中存放的是地址(字符串的首地址),决不是将字符串放到字符指针变量中。( 2 )对字符数组只能对各个元素赋值,不能用以下办法对字符数组赋值。 char str[14] ; str="I love China!" ; 而对字符指针变量,可以采用下面方法赋值: char *a ; a="I love China! " ; 但注意赋给 a 的不是字符串,而是字符串的首地址。
12.5 字符串的指针和指向字符串的指针变量二、字符指针变量与字符数组
第十二章 指针
( 3 )对字符指针变量赋初值时:char *a="I love China! " ; 等价于:char *a ; a="I love China! " ;而对数组初始化时:char str[14]={ " I love China! "} ;不等价于:char str[14] ; str[ ]="I love China! " ;即数组可以在变量定义时整体赋初值,但不能在赋值语句中整体赋值。
12.5 字符串的指针和指向字符串的指针变量二、字符指针变量与字符数组
第十二章 指针
( 4 )在定义一个数组时,在编译时即已分配内存单元,有固定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以存放一个地址值,也就是说,该指针变量可以指向一个字符型数据,但如果未对它赋以一个地址值,则它并未具体指向哪一个字符数据。如: char str [10] ; scanf ("%s" , str) ; 是可以的,而下面的形式是错误的: char * a ; scanf(“%s” , a) ;( 5 )指针变量的值是可以改变的。
12.5 字符串的指针和指向字符串的指针变量二、字符指针变量与字符数组
第十二章 指针
[ 例 12.16] 程序示例。main ( ){ char a=“I love China! ” ; /*a 指向存放字符 'I' 的存储单元 */ a=a + 7 ; /*a 指向存放字符 'C' 的存储单元 */ printf("%s" , a) ; /* 将输出 China! /*}数组名代表一个固定的地址,它的值是不能改变的。说明:定义一个指针变量并使它们指向一个字符串后,也可以用下标形式引用指针所指的字符串中的字符
( 与前面介绍的数组类似 ) 。
12.5 字符串的指针和指向字符串的指针变量二、字符指针变量与字符数组
第十二章 指针
(6) 不要随意使用无确定指向的指针。有时为了防止无确定指向的指针破坏有用数据,给暂时不用的指针赋 NULL 。如: int *p ; p=NULL ;其中 NULL 是在文件 stdio.h 中定义的符号常量,它的代码值为 0 ,这时称 p 为空指针。以下三种写法等价: p=NULL ; p='\0' ; p=0 ;使用 NULL 时,应在程序的开头加 #include<stdio.h> 。当企图通过空指针访问一个存储单元时,将显示一个出错信息。
12.5 字符串的指针和指向字符串的指针变量二、字符指针变量与字符数组
第十二章 指针
将一个字符串从一个函数传递到另一个函数,可以用地址传递的办法,即用字符数组名或用指向字符串的指针变量作参数。和数组一样,函数的首部有三种说明形式,而且形参也是指针变量。在被调用的函数中可以改变字符串的内容,在主调函数中可以得到改变了字符串。
12.6 字符串指针做函数参数
第十二章 指针
[ 例 12.17] 将字符数组中的字符串按逆序存放后输出。 #include<stdio.h> #include<string.h> main( ) { int i , j ; char ch [80] ; gets(ch) ; puts (ch) ; j=strlen (ch)- 1 ; fun(ch , j) ; puts (ch) ; } fun (char *p , int j) { int i ; char t , *q ; q=p + j ; for( ; p<q ; p ++, q-- ) { t=*p ; *p=*q ; *q=t ;} } 运行结果是:asdfgh<回车>asdfgh hgfdsa
12.6 字符串指针做函数参数
第十二章 指针
[ 例 12.18] 从键盘输入一个字符串,计算该字符串的长度。不要用 strlen 函数。 #include< stdio.h> main ( ) { int len ; char a [80] ; gets (a) ; puts (a) ; len=lenth(a) ; printf("%d\n" , len) ; }lenth(char *p){ char *q=p ; /* p 和 q都指向数组 a*/ while (*q!= '\0') q ++; /* 只移动 q , p 不变 */ return q- p ; /*q- p 表示共移动几个存储单元 */}运行结果是 asdfgh<回车> asdfgh 6
12.6 字符串指针做函数参数
第十二章 指针
[ 例 12.19]编一程序,将两个字符串连接起来。不要用 strcat 函数。 #include< stdio.h> main ( ) { char sl [80] , s2[40] ; printf("\n Input string1: ") ; gets(s1) ; printf("\n Input string2:) ; gets(s2) ; scat(s1 , s2) ; printf("\n New string : %s" ,
s1) ; }scat(char *s1 , char *s2) { while(*s1!='\0') s1 ++; while(*s2!='\0') { *s1=*s2 ; s1 ++ ; s2 ++; } *s1='\0' ;}运行情况: Input string 1 : country<回车> Input string 2 : side <回车> New string : countryside
12.6 字符串指针做函数参数
第十二章 指针
[ 例 12.20]编写一个程序,将字符数组 from 中的全部字符拷贝到字符数组 to 中。不要用 strcpy 函数。拷贝时, '\0' 也要拷贝过去。 '\0' 后面的字符不拷贝。#include< stdio.h>#include< string.h>main ( ){ char from [80] , to[80] ; printf("Input , string : ") ; scanf("%s , from) ; strcopy(from , to) ; printf("Copied string : %s/n" , to) ; }strcopy(char *from , char *to){ int i ; for(i=0 ; i< =strlen (from) ; i ++ ) to[i]=from[i] ; }运行结果: Input string : student<回车> Copied string : student
12.6 字符串指针做函数参数
第十二章 指针
[ 例 12.21]编写一个程序,比较字符数组 s1 和 s2 。不要用 strcmp 函数。#include< stdio.h>main ( ){ int a ; char s1[80] , s2[80] ; gets (s1) ; gets(s2) ; puts(s1) ; puts(s2) ; a=strcomp(s1 , s2) ; if(a>0) printf("(s1 : %s)>(s2 : %s)\n" , s1 , s2) ; if(a= = 0) printf("(s1 : %s)=(s2 : %s)\n" , s1 , s2) ; if(a<0) printf("(s1 : %s)<(s2 : %s)\n" , s1 , s2) ;}strcomp(char *s1 , char *s2){ while(*s1= = *s2&&. *s1!= '\0') {s1 ++; s2 ++; } return *s1- *s2 ;}运行结果是: boy<回车> girl<回车> boy girl (s1 : boy)< (s2 : girl)
12.6 字符串指针做函数参数
第十二章 指针
可以用指针变量指向整型变量、字符串、数组,也可以指向一个函数。一个函数在编译时被分配一个入口地址。这个入口地址就称为函数时的指针。可以用一个指针变量指向函数,然后通过该指针变量调用此函数。
12.6 字符串指针做函数参数一、用函数指针变量调用函数
第十二章 指针
main ( ){ int max (int , int ) ; int (*p) (int , int ) ; int a,b,c ; p=max ; scanf (“%d , %d “,&a,&b) ; c=(*p)(a,b) ; printf("max=%d\n " , c) ;}int max (int x , int y) /* 定义 max 函数 */{ int z ; if(x > y) z = x ; else z=y ; return (z) ;}main ( ){ int max (int , int ) ; int (*p) (int , int ) ; int a,b,c ; p=max ; scanf (“%d,%d”,&a,&b) ; c=(*p)(a,b) ; printf("max=%d\n " , c) ;}int max (int x , int y) /* 定义 max 函数 */ { int z ; if(x > y) z = x ; else z=y ; return (z) ;}
12.6 字符串指针做函数参数一、用函数指针变量调用函数
第十二章 指针
说明:(1) 指向函数的指针变量的一般定义形式为: 数据类型标识符 (* 指针变量名 )( 类型 参数 1, 类型 参数 2, ….) “ 数据类型标识符”是指函数返回值的类型,旧版本允许省略后一括号中的内容。(2) 函数的调用可以通过函数名调用。也可以通过函数指针调用 ( 即用指向函数的指针变量调用 ) 。(3) (*p)(int , int ) 表示定义一个指向函数的指针变量,它不是固定指向哪一个函数的,而只是表示定义了这样一个类型的变量,它是专门用来存放函数的入口地址。在程序中把哪一个函数的地址赋给它,它就指向哪一个函数。
12.6 字符串指针做函数参数一、用函数指针变量调用函数
第十二章 指针
(4) 在给函数指针变量赋值时,只需要给出函数名而不必给出参数。如: p=max ; 因为是将函数入口地址赋给 p ,而不牵涉到实参与形参的结合问题。不能写成“ p=max (a ,b) ;”形式。
(5) 用函数指针变量调用函数时,只需将( *p )代替函数名即可( p 为指针变量名),在( *p )之后的括弧中根据需要写上实参,
(6) 对指向函数的指针变量,象 p+n 、 p++ 、 p--等运算无意义的。(7) 函数指针变量常用的用途之一是把指针作为参数传递到其它函数。
12.6 字符串指针做函数参数一、用函数指针变量调用函数
第十二章 指针
函数的指针变量也可以作为参数,以便实现函数地址的传递,也就是将函数名传给形参。 它的原理可以简述如下:有一个函数(假设函数名为 sub ),它有两个形参( x1 和 x2 ),定义 x1 和 x2 为指向函数的指针变量,在调用函数
sub 时,实参用两个函数名 f1 和 f2 给形参传递函数地址,这样在函数 sub 中就可以调用 f1 和 f2 函数了。
12.6 字符串指针做函数参数二、把指向函数的指针变量作为函数参数
第十二章 指针
一个函数不仅可以带回简单类型的数据,而且可以带回指针型的数据,即地址。如:#include < stdio.h>char *fun (char *) ; /* 指针类型也要原型说明 */main ( ){ char ch ='a' , *p , *q ; p=&ch ; q=fun(p) ; /* 调用结束后 q才有确定的指向,相当于 q="bag" ; */ puts (q)}char * fun (char *s){ char *t="big" ; *( t + 1 ) = *s ; /* *s 相当于主函数中的 *p 即 ch */ return t ; /*返字符串的首地址 */}输出结果是:bag
12.7 返回指针值的函数
第十二章 指针
一个数组,其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都是指针变量。 形式:类型标识符 * 数组名 [ 数组长度说明 ] ;如: int *p[4] ; 注意:不要写成 int ( *p ) [ 4 ] ;这是指向一维数组的指针变量。指针数组使字符串处理更方便灵活。
12.8 指针数组和指向指针的指针一、指针数组
第十二章 指针
[ 例 12.22] 在五个字符串中,找出最大者,并使下标为 0 的指针数组元素指向它。#include < stdio.h>#include < string.h> main ( ) { int i , k ; char *temp,*str [ ]={ "Follow”,"QBASIC”,"Great”,"FORTRA
N”,"Computer"}; k=0 ; for ( i =1 ; i< 5 ; i ++ ) if(strcmp(str[k],str[i])< 0) k=i ; if (k!=0) { temp=str[0] ; str[0]=str[k] ; str[k]=temp ; } printf("The largest string is\n%s\n" , str[0]) ; }运行结果是: QBASIC
12.8 指针数组和指向指针的指针一、指针数组
第十二章 指针
指针变量也有地址,这地址可以存放在另一个指针变量中。如果变量 p 中存放了指针变量 q的地址,那末 p 就指向指针变量 q 。指向指针数据的指针变量,简称为指向指针的指针。 定义一个指向字符型指针数据的指针变量,形式如下: char * * p ; 如果有 char *q="abc" ;则 p=&q ;是合法的。 *p 相当于 q , **p 相当于 *q ,因此, **p 中的值为 'a' ,
12.8 指针数组和指向指针的指针二、指向指针的指针
第十二章 指针
[ 例 12.23] 写出下面程序地运行结果。main ( ) { char *str [ ] ={“ENGLISH”,“MATH”,“MUSIC”, “PHYS
ICS”,"CHEMISTRY"} ; char **q ; int num ; q=str ; for(num=0 ; num<5 ; num ++ ) printf("%s\n" , *(q ++ )) ;}运行结果是:ENGLISHMATH MUSIC PHYSICS CHEMISTRY
12.8 指针数组和指向指针的指针二、指向指针的指针
第十二章 指针
main 函数可以有参数,形式: main (int argc , char **argv ) argc 和 argv 是 main 函数形参。实参从命令行得到。 命令行形式:命令名 参数 1 参数 2 …… 参数 n argc 是指命令行中参数的个数,参数含文件名,因此 argc≥1 。 argv 是指向字符指针数组的指针
( 即指向指针的指针 ) ,它指向的指针数组的每一元素都指向一个字符串,
12.8 指针数组和指向指针的指针三、 main 函数的命令行参数
第十二章 指针
[ 例 12.24] 下面程序的文件名为 file.c ,写出程序的运行结果。 main ( int argc , char * argv [ ] ) { argc-- ; argv++ ; while(argc> 0) { printf("%s" , *argv) ; argc-- ; argv++ ; }}如果命令输入: c :> file Computer and C Language<回车>则输出: Computer and C Language
12.8 指针数组和指向指针的指针三、 main 函数的命令行参数
第十二章 指针
如有命令行: filel China Beijing argc 的值等于 3 , argv[0] 指向‘ filel’ ,
argv[1] 指向‘ China’ , argv[2] 指向‘ Beijing’ 。
12.8 指针数组和指向指针的指针三、 main 函数的命令行参数