9512.net
甜梦文库
当前位置:首页 >> 工学 >>

第8章 善于利用指针



第八章 善于利用指针
? ? ? ? ? ? ? ?

地址和指针的概念 变量的指针和指向变量的指针变量 数组与指针 字符串与指针 指向函数的指针 返回指针值的函数 指针数组和指向指针的指针 指针的数据类型和指针运算

学习指针的重要性
?指针是C语言中广泛使用的一种数据类型,运用指针编 程是C语言最主要的风格之一。<

br />
?利用指针变量可以表示各种数据结构;能很方便地使用 数组和字符串;并能象汇编语言一样处理内存地址,从而 编出精练而高效的程序。 ?指针极大地丰富了C语言的功能。学习指针是学习C语 言中最重要的一环,能否正确理解和使用指针是我们是否 掌握C语言的一个标志。
?指针是C语言中最为困难的一部分,在学习中除了要正 确理解基本概念,还必须要多思考、多比较、多编程,多 上机,在实践中掌握它。

变量的指针和指向变量的指针变量
?通常把存放数据的内存单元的地址称为指针。 ?在C语言中,允许用一个变量来存放指针,这种变量称为指 针变量。因此,一个指针变量的值就是某个内存单元的地 ?即:一般变量用来存储变量的值;指针变量是用来保存变量 地址的变量;变量的地址又称变量的指针,是一个常量。 ?定义指针变量的一般形式: 数据类型 *指针变量名; 1000 ’A’ 变量 c ?若有:char *pc; 1001 ?则称指针变量pc是char型指针 …… ?pc=&c; /* &取c的地址 */ ?则称指针变量pc指向变量c 2000 1000 变量 pc ?*pc表示pc所指向的变量,即变量c ?一个指针变量只能指向同一个类型的变量

指针变量的引用
指针运算符
?运算符(单目 ← ) & 取变量的地址 2 * 取指针变量(所指向)的内容 2 ?例: int i=3; int *i_pointer=&i; (注:不允许把一个数赋予指针变量)

下面两个语句作用相同: i=5; *i_pointer=5;

指针变量的引用
例:输入a和b两个整数,按先大后小的顺序输出a和b。 void main( ) { int *p1,*p2,*p,a,b; scanf(“%d,%d”,&a,&b); p1=&a; p2=&b; if(a<b) { p=p1; p1=p2; p2=p; } printf(“\na=%d,b=%d\n\n”,a,b); printf(“max=%d,min=%d\n”,*p1,*p2); } 运行情况如下: 5,9 a=5,b=9 max=9,min=5

指针变量作为函数参数
例:用函数交换两个变量的值。 #include <stdio.h> void main ( ) { void swap(int *px,int *py); int a, b; a=5; b=10; printf ("before swap a=%d, b=%d\n", a, b); swap( &a, &b ); /* 实参为变量a和b的地址 */ printf ("after swap a=%d, b=%d\n", a, b); } void swap(int *px,int *py) /* 形参为指向整型的指针 */ { int temp; temp = *px; /* 将指针变量px的内容赋给变量temp */ *px = *py; /* 将指针py的内容赋给指针px的内容 */ *py = temp; /* 将变量temp的值赋给指针py的内容 */ printf ("in swap x=%d, y=%d\n", *px, *py); }

指针变量作为函数参数
?为了使在函数中改变了的变量值能被main函数所用,应该 用指针变量作为函数参数,在函数执行过程中使指针变量所 指向的变量值发生变化,函数调用结束后,这些变量值的变 化依然保留下来。即指针参数使得被调用函数能够访问和修 改主调函数中变量的值。 ?注意1:下面的写法有问题

void swap(int *p1,int *p2)
{int *temp; *temp=*p1; /*此语句有问题*/ *p1=*p2; *p2=*temp; }

?注意2:不能企图通过改 变指针形参的值而使指针实 参的值改变
void swap(int *p1,int *p2)

{

int *p; p=p1; p1=p2; p2=p; }

指针变量作为函数参数
例:输入a、b、c3个整数,按大小顺序输出。 void swap(int *pt1,int *pt2) { int temp; temp=*pt1; *pt1=*pt2; *pt2=temp; } void exchange(int *q1,int *q2,int *q3) { if(*q1<*q2) swap(q1,q2); if(*q1<*q3) swap(q1,q3); if(*q2<*q3) swap(q2,q3); } void main() { int a,b,c,*p1,*p2,*p3; scanf(“%d,%d,%d”,&a,&b,&c); p1=&a; p2=&b; p3=&c; exchange(p1,p2,p3); printf(“\n%d,%d,%d\n”,a,b,c); }

数组与指针
?在C语言中,指针和数组之间的关系十分密切,通过数组下 标所能完成的任何操作都可以通过指针来实现。一般,用指 针编写的程序执行速度快,但用指针实现的程序理解起来困 难一些。 ?定义一个指向数组元素的指针变量的方法,与以前介绍的 指针变量相同。 例如:int a[10]; int *p; /*定义p为指向整型变量的指针*/ p=&a[0]; /*对指针变量赋值*/ ?C 语言规定,数组名代表数组的首地址,也就是第 0 号元素 的地址。因此,下面两个语句等价: p=&a[0]; ←→ p=a;

指向数组元素的指针
?在定义指针变量时可以赋给初值: int *p=&a[0]; 等价于: int *p; p=&a[0]; 也可以写成: int *p=a; ?C语言规定:如果指针变量 p已指向数组中的一个元素,则p+1 指向同一数组中的下一个元素。 ?引入指针变量后,就可以用两种方法来访问数组元素了。 如果p的初值为&a[0],则: 1)p+i和a+i就是a[i]的地址,或者说它们指向a数组的第i个元 素。 2)*(p+i)或*(a+i)就是p+i或a+i所指向的数组元素,即a[i]。 例如,*(p+5)或*(a+5)就是a[5]。 3)指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价。

通过指针引用数组元素
?因此,引用一个数组元素 可以用: 1)下标法,即用a[i]形式访 问数组元素。在前面介绍数 组时都是采用这种方法。 2)指针法,即采用*(a+i)或 *(p+i)形式,用间接访问的 方法来访问数组元素。 ?注意:指针变量可以实现 本身的值的改变。如p++是合 法的;而a++是错误的。因为 a是数组名,它是数组的首地 址,是常量。

通过指针引用数组元素
例:输入和输出数组中的全部元素 void main( ) void main( ) { int a[10],i; int *p; { int a[10],i,*p; for(i=0;i<10;i++) p=a; scanf(“%d”,&a[i]); for(i=0;i<10;i++) for(i=0;i<10;i++) scanf(“%d”,p++); printf(“%d”,a[i]); p=a; } *(a+i) for(i=0;i<10;i++,p++) for(p=a;p<(a+10);p++) printf(“%d”,*p); printf(“%d”,*p); } 注 for(p=a;a<(p+10);a++) 意 printf(“%d”,*a);

数组名或指针变量作函数参数
例:将数组a中n个整数按相反顺序存放。 void inv(int *x,int n) void inv(int x[],int n) {int temp,m=(n-1)/2; {int temp,i,j,m=(n-1)/2; int *p,*i,*j; for(i=0;i<=m;i++) i=x; j=x+n-1; p=x+m; {j=n-1-i; for(;i<=p;i++,j--) temp=x[i];x[i]=x[j];x[j]=temp;} {temp=*i;*i=*j; } *j=temp;} void main( ) } {int i,a[10]={3,7,9,11,0,6,7,5,4,2}; for(i=0;i<10;i++) printf(%d,”,a[i]); printf(“\n”); inv(a,10); for(i=0;i<10;i++) printf(“%d,”,a[i]); }

数组名或指针变量作函数参数
?归纳起来,如果有一个实参数组,想在函数中改变此数组的 元素的值,实参与形参的对应关系有以下4种情况: main() 实参 形参 { int a[10],*p; 数组名 数组名 p=a; 数组名 指针变量 · · · f(int *x,int x[],intn) n) f(p,10); 指针变量 数组名 { · · · 指针变量 指针变量 · · · } main() } f(int *x,int x[],intn) n) { int a[10]; { · · · · · · f(a,10); } · · · }

通过指针引用多维数组
设有整型二维数组a[3][4]的定义为: int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}} 设数组a的首地址为1000,各下标变量的首地址及其值如图 C语言允许把一个二维数组分解为 多个一维数组来处理。因此数组a 可分解为三个一维数组,即a[0]、 a[1]、a[2],每一个一维数组又含 有四个元素。

多维数组的地址
从二维数组的角度来看,a是二维数组名,a代表整个二维数组的首地址,也 是二维数组0行的首地址,等于1000。a+1代表第一行的首地址,等于1008。 如图:

?a,a[0],*(a+0),*a,&a[0][0]是相等的, 同理, a+1,a[1],*(a+1),&a[1][0]是等同的。 ?由此可得出:a+i,a[i],*(a+i),&a[i][0]是等同的。此外,&a[i]和 a[i]也是等同的。另外,a[0]也可以看成是a[0]+0,是一维数组a[0]的0 号元素的首地址,而a[0]+1则是a[0]的1号元素首地址,由此可得出 a[i]+j则是一维数组a[i]的j号元素首地址,它等于&a[i][j]。 ?由a[i]=*(a+i)得a[i]+j=*(a+i)+j。由于*(a+i)+j是二维数组a的i行j 列元素的首地址,所以,该元素的值等于*(*(a+i)+j)。

指向多维数组元素的指针变量
例:已知 int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; 求: A) *(a+1)+2 即a[1][2]的地址 B) *(a[0]+6) 即数组元素a[1][2],等于7 C) *(a[1]+2) 即数组元素a[1][2],等于7 D) *(&a[0][0]+6) 即数组元素a[1][2],等于7 E)*(*(a+1)+2) 即数组元素a[1][2],等于7 例:用指针变量输出数组元素的值 void main( ) {int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int *p; int i,j,*p; for(p=a[0];p<a[0]+12;p++) p=a[0]; printf(“%4d”,*p); for(i=0;i<3;i++) } for(j=0;j<4;j++) printf(“%4d”,*(p+i*m+j)); a[i][j]在数组中的相对位置

指向由m个元素组成的一维数组的指针变量
?又称为数组指针,其说明形式为: 数据类型 ( * 指针变量名)[常量表达式] ?例如:int (*pa)[6]; 含义:定义了一个指向数组的指针,被指向的数组是一 个有6个元素的整型一维数组。

pa
注意:pa+1将 指向下一个一 维数组 pa+1

整数 整数 整数 整数 整数 整数

(*pa)[0] (*pa)[1] (*pa)[2] (*pa)[3] (*pa)[4] (*pa)[5]

指向由m个元素组成的一维数组的指针变量
例:输出二维数组任一行任一列元素的值 void main( ) { int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int (*p)[4],i,j; p=a; scanf(“i=%d,j=%d”,&i,&j); printf(“a[%d,%d]=%d\n”,i,j,*(*(p+i)+j)); } 注意区分:p+i 和 *(p+i) (p+i)+j 和 *(p+i)+j 例如:p+2 和 *(p+2)具有相同的值, 但(p+2)+3 和 *(p+2)+3 的值就不相同

多维数组的指针作函数参数
?在用指针变量作形参以接受实参数组名传递来的地址时,有 两种方法:1)用指向变量的指针变量;2)用指向一维数组的 指针变量 例:有一个班,3个学生,各4门课,计算总平均分数,以及第n 个学生的成绩 void average(float *p,int n) #include<stdio.h> {float *p_end,aver,sum=0; void main( ) p_end=p+n-1; {void average(float *p,int n) for(;p<=p_end;p++) sum=sum+(*p); void search(float (*p)[4],int n); aver=sum/n; printf(“average=%5.2f\n”,aver);} float score[3][4] ={{65,67,70,60},{80,87,90,81},{90,99,100,98}}; average(*score,12); void search(float (*p)[4],int n) search(score,2); {int i; printf(“No.%d score are:\n”,n); } for(i=0;i<4;i++) printf(“5.2f”,*(*(p+n)+i));}

字符串与指针
?字符串的表示形式
(1)用字符数组存放一个字符串,然后输出该字符串 void main( ) { char string[]=“I love China!”; printf(“%s\n”,string); } (2)用字符指针指向一个字符串 void main( ) { char *string=“I love China!”; printf(“%s\n”,string); } char *string; string=“I love China!”; 注意:这里是把存放字符串的字 符数组的首地址赋给string,它 只能指向一个字符型数据

字符串与指针
?字符串指针变量的定义说明与指向字符变量的指针变量说明 是相同的。只能按对指针变量的赋值不同来区别。对指向字符 变量的指针变量应赋予该字符变量的地址。 ?如: char c,*p=&c; 表示p是一个指向字符变量c的指针变量。 而: char *s="C Language"; 则表示s是一个指向字符串的指针变量。把字符串的首地址赋 予s。即等价于: char *s; s="C Language"; ?例: void main( ) { char *ps="this is a book"; ps=ps+10; printf("%s\n",ps); }

字符串的复制——用指针实现
void main( ) 例:将字符串a复制为字符串b。 {char a[]=“I am a boy.”; void main( ) char b[20],*p1,*p2; {char a[]=“I am a boy.”,b[20]; int i; int i; p1=a; p2=b; for(i=0;*(a+i)!=?\0?;i++) for(;*p1!=?\0?;p1++,p2++) *(b+i)=*(a+i); *p2=*p1; *p2=?\0?; *(b+i)=?\0?; printf(“string a is:%s\n”,a); printf(“string a is:%s\n”,a); printf(“string b is:”); printf(“string b is:”); for(i=0;b[i]!=?\0?;i++) for(i=0;b[i]!=?\0?;i++) printf(“%c”,b[i]); printf(“%c”,b[i]); printf(“\n”); printf(“\n”); } }

字符串与指针
?字符串指针作函数参数
例: 字符串的复制。 void 用函数调用实现 strcopy(char *str1,char *str2) void strcopy(char str1[],char str2[]) /* 将str1拷贝到str2中*/ { while(*str1!= ?\0 ?) { while(str1[i]!= ?\0?) { *str2=*str1; { str2[i]=str1[i]; str1++; str2++; } i++; } str2[i]= ?\0 *str2=?\0 ?; ?; } } void main( ) *a “I am a teacher.”; { char a[]= *b “you are a student.” char b[]= printf ("a=%s\nb=%s\n", a, b ); strcopy ( a, b ); /* 函数的实参为数组名 */ printf ("a=%s\nb=%s\n", a, b ); }

字符串指针作函数参数
//调用函数f,从字符串中删除所有的数字字符。 #include <stdio.h> #include <string.h> #include <ctype.h> void f(char *s) { int i=0; while(s[i]!='\0') { if(isdigit(s[i])) strcpy(s+i,s+i+1); else i++; } } void main() { char str[80]; gets(str); f(str); puts(str); }

指向函数的指针变量
?

?

程序只有装入内存才能运行。在内存中也要给函数分配一 个入口地址, 因此通过定义一个指向该函数的指针, 即可 引用该函数。 指向函数的指针变量的定义形式为:

数据类型
?

(*指针变量名)(函数参数表列 );

?

定义了指向函数的指针变量,并不表示指向哪个具体的函数, 要想指向具体的函数,还必须给它赋值。 指向函数的指针赋值的一般格式:

指针变量名=函数名;
?

例如: int (*p)(int,int),max(int,int); p=max;

指向函数的指针变量
?
?

用函数指针变量调用函数
指向函数的指针赋值后,即可引用,其一般格式为:

(*指针变量名)(函数实参表);
?

例如,求两个数的最大值: int a,b,(*p)(int,int),max(int,int),res; p=max; /* 不能写成 p=max(a,b); */ ……. res=(*p)(a,b); /* 与 res=max(a,b); 等价 */

注意:p是指向函数的指针变量,它只能指向函数的入口处而 不可能指向函数中间的某一条指令处,因此不能用*(p+1) 来表示函数的下一条指令。在一个程序中,一个指针变量可以 先后指向不同的函数。对p作p+n、p++、p--等运算无意义。

用指向函数的指针做函数参数
int max( int x,int y) { return(x>y ? x : y);} int min( int x, int y) { return(x<y ? x : y);} int add( int x, int y) { return(x + y); } int mult( int x, int y ) { return(x * y); } void main( ) { int a,b; printf(“Enter a,b:”); scanf(“%d%d”,&a,&b); process( a,b,max,“max=”); process( a,b,min,“min=”); process( a,b,add,“add=”); process( a,b,mult,“mult=”); }

void process(int x,int y,int (*fun)(int,int),char *s) { int res; res=(*fun)(x,y); printf(“ %s %d\n”,s,res); }

返回指针值的函数
?函数的返回值是一个指针(即地址)
?函数的定义形式: 函数类型 *函数名(参数列表) 例如: char *strchr(char *str,char ch) { while(*str!=ch) str++; return(str); } void main( ) { char ch=?o?,a[]=“hello world!”,*p; p=strchr(a,ch); printf(“%c”,*p); printf(“%s”,p); } 比较: ? int *func( ); 返回地址的函数 , 说明了一个函数, 其返回值为指向整 型的指针; ? int (*func)( ); 指向函数的指针, 说明了一个指向返 回值为整型的函数 的指针变量。

指针数组
?数组中的元素均为指针类型,称之为指针数组。 ?指针数组说明的形式为: 数据类型 * 数组名[常量表达式] ?例如: int * pa[6]; 含义:定义一个由 6 个指针变量构成的指针数组,数组 中的每个数组元素━━指针,都指向一个整数。 指针数组pa
pa[0] pa[1] pa[2] pa[3] pa[4] pa[5] 整数 整数 整数 整数 整数 整数

?指针数组比较适合于用来指向若干个字符串,使字符串处理 更加方便灵活

指针数组
例:将若干字符串按字母顺序(由小到大)输出。 void main( ) { void sort(char *name[],int n); void print(char *name[],int n); char *name[]={ “Follow me”, “BASIC”, “Great Wall”, “FORTRAN”, “computer design” }; int n=5; sort(name,n); print(name,n); } void print(char *name[],int n) void sort(char *name[],int n) {int i; { char *temp; int i,j,k; for(i=0;i<n;i++) for(i=0;i<n-1;i++) printf(“%s\n”,name[i]); {k=i; } for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0) k=j; if(k!=i) {temp=name[i]; name[i]=name[k]; name[k]=temp;} } }

指向指针的指针
? ?

?

存放指针地址的变量称为“指针的指针”。 定义形式为: 数据类型 **指针变量名; 例如: int x=5, *xp, **xpp; xp = &x; xpp = &xp; printf(“%d ”,x ); /*直接访问*/ printf(“%d ”,*xp ); /*单级间址访问*/ printf(“%d ”,**xpp ); /*二级间址访问*/

指向指针的指针
例: void main( ) { char *name[]={ “Follow me”, “BASIC”, “Great Wall”, “FORTRAN”, “computer design” }; char **p; int i; for(i=0;i<5;i++) { p=name+i; printf(“%s\n”,*p); } } void main( ) { int a[5]={1,3,5,7,9}; int *num[5],**p,i; for(i=0;i<5;i++) num[i]=&a[i]; p=num; for(i=0;i<5;i++) { printf(“%d\t”,**p); p++; } }

例:

指针数组作main函数的形参
?main函数参数的一般形式:
main ( int argc, char *argv[ ] ) argc表示命令行参数个数,argv指向命令行参数的指针数组 ?main函数是由系统调用的,当在操作系统下运行C程序时,可 以使用命令行参数形式,向main函数传递参数。命令行参数的 一般形式: 运行文件名 参数1 参数2 …… 参数n argc=n+1 数组argv
argv[0] argv[1] argv[2] ..... argv[argc-1] 文件名 第1个参数 第2个参数 ......

......

第argc-1(n)个参数

有关指针的数据类型和指针运算小结
int *p; int *q[6]; int (*w)[6]; int *g( ); int (*y)( ); int **x; p 是一个指向整型数据的指针变量 根据优先级,q先和[]结合,所以 q 是一个指 针数组,该数组有6个元素。 ( )内的*w指示出w是一个指针,指向一个含6个 元素的一维数组。w是数组指针。 根据优先级, g先和( )结合, 所以g是一个函 数,*说明函数的返回值是指向整型数据的指针 (*y)说明y是一个指针,( )表明此指针是指向 函数的,函数的返回值是整型。 x是一个指针变量,它指向一个指向整型数据的 指针变量

void指针类型
?

?

?

?

?

?

C语言规定,可以说明指向void类型的指针, 即可定义一个 通用型的指针, 可以指向任何类型的变量。 将void型指针值赋给另一指针变量时要进行强制类型转换。 使之适合于被赋值的变量的类型。 例如:char *p1; void *p2; · · · p1=(char *)p2; 同样可以用(void *)p1 将p1的值转换成void *类型。如: p2=(void *)p1; 也可以将一个函数定义为void *类型,如: void *fun(char ch1,char ch2) 表示函数fun返回的是一个地址,它指向“空类型”,如需 要引用此地址,也需要根据情况对之进行类型转换,如对函 数调用得到的地址要进行以下转换: p1=(char *)fun(ch1,ch2);



更多相关文章:
第8章 善于利用指针.ppt.Convertor
第8 章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针 8.6 返回指针值的函数 8.7 指针数组...
第8章 指针
第8章 指针(新) 72页 免费 第8章善于使用指针 42页 免费 第8章 指针-2 ...新疆农业大学С语言程序设计课程教案一、教学目的和要求 了解指针变量的定义和初始...
善于利用指针(指针基础)-1
教学内容 第8章 善于利用指针 本章知识点 ? 指针的概念 ? 指针变量 ? 指针与数组 授课要点 ? 变量的地址和指针变量的概念 ? 指针变量的定义和引用 问题 1 ...
第8章-指针
72页 免费 第8章善于使用指针 42页 免费 第8章 指针-2 52页 免费 第8章 指针2 30页 2财富值 第8章 灵活的指针 24页 免费如要投诉违规内容,请到百度文库...
C语言-第8章 指针
第8 章 善于利用指针一、单项选择题 1. 语句 int *p;说明了 A)p 是指向一维数组的指针 C)p 是指向 int 型数据的指针 2. 变量的指针,其含义是指该变量...
第8章 指针
第8章 指针(新) 72页 免费 第8章善于使用指针 42页 免费 第8章 指针-2 52页 免费 第8章 指针2 30页 2财富值 第8章 灵活的指针 24页 免费喜欢...
第8章 指针
第8章 善于利用指针 213页 免费 第8章 指针2 30页 2财富值 第8章 灵活的指针 24页 免费如要投诉违规内容,请到百度文库投诉中心;如要提出功能问题或意见建议...
2C 第8章 指针
第8章 指针 48页 免费 第8章 指针(新) 72页 免费 第8章 善于利用指针 213...第4章 选择结构程序设计 37页 免费如要投诉违规内容,请到百度文库投诉中心;如...
第8章 指针
第8章 善于利用指针 213页 免费 第8章 指针2 30页 2财富值 第8章 灵活的指针 24页 免费如要投诉违规内容,请到百度文库投诉中心;如要提出功能问题或意见建议...
c语言 第八章 指针
C语言 第八章 指针1 62页 免费 第八章 善于利用指针(c语... 88页 2下载...指针数组和多级指针 一、指针的概念 (1)掌握变量与地址的关系 (2)掌握指针与...
更多相关标签:
善于利用资源的成语    善于利用资源    善于利用资源的事例    成功需要善于利用资源    善于利用资源的例子    要懂得善于利用资源    善于利用时间    善于利用资源的故事    

All rights reserved Powered by 甜梦文库 9512.net

copyright ©right 2010-2021。
甜梦文库内容来自网络,如有侵犯请联系客服。zhit325@126.com|网站地图