390 likes | 562 Views
第 8 章 指 针. 8.1 指针的基本概念 8.2 指针和指针变量 8.3 一维数组和指针 8.4 指针数组 8.5 指针与函数 8.6 指针的指针 8.7 指针 与二维数组 8.8 main() 函数的参数. 第 8 章 指针. 8.1 指针的基本概念. 指针就是地址,是一种数据类型。 它是用来表示另外变量的地址。 “直接访问”方式:按变量地址直接对变量的值进行存取。
E N D
第8章 指 针 • 8.1 指针的基本概念 • 8.2 指针和指针变量 • 8.3 一维数组和指针 • 8.4指针数组 • 8.5 指针与函数 • 8.6 指针的指针 • 8.7 指针与二维数组 • 8.8 main()函数的参数
第8章 指针 8.1 指针的基本概念 指针就是地址,是一种数据类型。它是用来表示另外变量的地址。 “直接访问”方式:按变量地址直接对变量的值进行存取。 “间接访问”方式:在访问变量时,不直接按变量的地址取其值,而将变量的地址存放在另一个存储单元中,要访问某变量时,先访问存放该变量地址的存储单元,再间接地访问变量,对变量进行存取操作。 返回章目录
第8章 指针 8.2 指针和指针变量 可以用运算符“*”来定义指针变量,也可以用“*”表示“指向”关系来使用指针变量。 8.2.1 指针变量的定义 指针变量是专门用于存放地址的变量,C语言将它定义为“指针类型”。定义指针变量的一般格式为:类型标识符 * 指针变量名 例如: int * p ; 我们说:p 是指向整型数据的指针,p的值是整型变量的地址。
第8章 指针 8.2.2 指针变量的赋值 与指针有关的运算符有两个: 运算符“&”:求变量的地址;*求指针所指变量的值。 可以用赋值语句使一个指针变量指向一个变量,例如: int i,j,*p1; p1=&i ; j = *p1; 也可以在定义指针变量的同时对其赋值,例如: int i=3 , *p1=&i ; int *p1=&i 相当于:int *p1; p1 = &i;
第8章 指针 指针变量的赋值 (1)指针变量定义和赋值注意: 例如: int i,*p, *p1=&i; *p=i ; 或 *p = *p1; 危险动作!,不知p指向那里,不能它赋值 应该:int *p, j; p=0; 或p=‘\0’; 或 p=NULL 或 p=&j; 然后,*p=i; 先让它指到一个“安全”地带,再给它赋与内容 (除0以处,不能把非地址整型值赋给指针) (2)指针变量互相赋值: int i=3 , *p1,*p2 ; p1=&i; p2 = p1; 使指针变量p2指向p1所指变量, p1,p2同时指向i变量。
第8章 指针 x d d 例:指针运算符 void main( ) { int d,x,*p,*q; d=5;p=&d; x=*p; printf("x=%d\n",x); *p=7; printf(“d=%d\n",d); q=p; printf(“*q=%d\n",*q); } q q p
第8章 指针 *和&是互逆运算。 已知:int a,*p; p=&a; 请考虑: *&a 与 a的关系 *&p 与 &*p 与p的关系 指针运算符: “*”和“&”优先级相同,自右向左运算。 “&”只能用于变量和数组元素。 void main( ) { int d,p; d=4; p=*&d; printf("p=%d\n",p); }
第8章 指针 8.2.3 指针变量的引用 可以通过指针运算符“*”引用指针变量,指针运算符可以理解“指向”的含义。 例:交换指针还是交换所指变量? void main( ) { int a=10,b=8,t,*p1,*p2,*pt; p1=&a;p2=&b; t=*p1;*p1=*p2;*p2=t; printf ("a =%d,b=%d\n",a,b); a=10; b=8; /*归位*/ pt=p1;p1=p2;p2=pt; printf("a=%d,b=%d\n",a,b); }
第8章 指针 8.2.4 指针变量作为函数参数 函数的参数是一般变量或常数时,函数实参向形参是单向值传递。 函数的参数是数组名时,则将实参数组名传递给形参数组名,数组名表示数组中第1个元素的地址,故这种传递是地址的传递。 函数参数也可以是指针变量,其作用是将变量的地址传到另一函数中去。 返回章目录
第8章 指针 指针变量作函数参数示例1:使函数返回多个值 void main( ) {int a=10,b=8; f(&a, &b); printf("a=%d,b=%d\n",a,b); } void f(int *x, int *y) /*函数f的功能是什么?*/ { *x=*x*2;*y=*y*2; }“遥控”作用。 x和y说:你只要让我指向你,我通过改变我指的内容,就能改变你!(类似文件副本与快捷方式)
第8章 指针 指针变量作函数参数示例2: 完善求一元二次方程根的函数getroot void main( ) {int a=3,b=8,c=2; float x1,x2; getroot(a, b,c,&x1,&x2); printf(“x1=%f,x2=%f\n",x1,x2); } void getroot(int a,int b,int c,float *root1, float *root2) { 补充内容; }
第8章 指针 指针变量作函数参数示例3:交换两个整数 void main( ) {int a=10,b=8; swap(&a,&b); printf(“%d,%d”,a,b) } void main( ) {int a=10,b=8; swap(a,b); printf(“%d,%d”,a,b) } void swap(int *x,int *y) {int t; /*用int *t行吗 */ t=*x;*x=*y;*y=t; }能交换 void swap(int x,int y) {int t; t=x;x=y;y=t; } 不能交换 void swap(int *x,int *y) {int *t; t=x; x=y; y=t; }不能交换 void swap(int *x,int *y) {int *t,q;t=&q; *t=*x;*x=*y;*y=*t; }能交换
第8章 指针 8.3 一维数组和指针 8.3.1 一维数组与指针 指针可以指向数组或数组元素. 一维数组中,第1个元素如a[0]的地址,即该数组的起始地址。可以用数组名方式,通过指向运算符“*”引用数组元素,也可以将指针变量指向一维数组,通过指针变量引用数组元素。例如: int a[10] , *p ; /* 定义a数组和指针变量p */ p=a ; /* a数组首地址→p */ 或p=&a[0] 使p指向了数组 a
第8章 指针 一维数组和指针示例 p+i是 a[i]的地址 ; *(p+i)是a[i]的值 . void main( ) {int *p1,*p2,*p3; static int a[ ]={1,2,3,4,5}; p1=a;p2=&a[2]; p3=p2+2; printf("a[ ]=%d\n",p1); printf("%d:%d\n",p2,*p2); printf("%d:%d\n",p3,*p3); } 结果: a[ ]=2003 2007:3 2011:5
第8章 指针 数组名常指针法: void main() {int a[]={1,2,3,4,5}; int i; for(i=0;i<5;i++) printf("%d\t", *(a+i)); } 不能使用a++ 指向数组的指针作为函数参数示例:下标法 void main() {int a[]={1,2,3,4,5}; int i; for(i=0;i<5;i++) printf("%d\t",a[i]); }
第8章 指针 两指针: void main() {int a[]={1,2,3,4,5}; int i,*p=a,*q=a+4; for(;p<=q;p++) printf("%d\t",*p); } 指针变量指向数组访问法: void main() {int a[]={1,2,3,4,5}; int i,*p=a; for(i=0;i<5;i++,p++) printf("%d\t",*p); }
第8章 指针 8.3.2 指向数组的指针作为函数参数 数组名作为函数参数,实现函数间地址的传递。指向数组的指针也可以作为函数参数,数组名和指针都是地址。在作为函数参数时有以下几种情况: 实参 形参 数组名 数组名 指针变量 指针变量 在实参向形参传递中,应保证其类型的一致性。 返回章目录
第8章 指针 形参,实参均为数组名: void inv(int x[],int n) {int t; int i,j; for(i=0;i<(n-1)/2;i++) {j=n-1-i;/*后边的下标*/ t=x[i];x[i]=x[j];x[j]=t; } }P237 数组名或指针作为函数形参与实参示例:逆置元素 void main() {int a[]={1,2,3,4,5}; int inv(int x[],int 5); inv(a,5); for(i=0;i<5;i++) printf("%d\t",a[i]); }
第8章 指针 形参指针,实参数组名: void inv(int *x,int n) {int *i,*p,*j; int t,m=(n-1)/2; i=x;j=x+n-1;p=x+m for(;i<=p;i++,j--) {t=*i;*i=*j;*j=t; } /*i左p终j右*/ }P238 数组名或指针作为函数形参与实参示例:逆置元素 void main() {int a[]={1,2,3,4,5}; int inv(int x[],int n); inv(a,5); for(i=0;i<5;i++) printf("%d\t",a[i]); }与前同
第8章 指针 8.3.3 指针与字符串 C语言中,一个字符串可以存放在一个字符数组中,数组名表示该字符串第一个字符存放的 地址,也可以将字符串的首地址赋给一个字符型指针变量中,该指针变量便指向这个字符串,或者说,指针变量可以指向任一字符串的首地址。 例如: char *str="I love China" ; 或 char *str ; str="I love China" ; char str[]= ="I love China" ; 可以 char str[20]; str[20]="I love China" ; 不可以
第8章 指针 main( ) {static char *p,s[ ]=" abcdef\n "; p=s; printf("%s\n",p); while(*p!=‘\0’) {printf("%c",*p++);} } 指向字符数组示例: 打印字符串 main( ) {static char s[ ]=" abcdef\n "; printf("%s\n",s); } main( ) {char *s=" abcdef\n "; printf("%s\n",s); } 注意: char s[ ] char *s
第8章 指针 指针与字符串例:字符串复制 void str_cpy(char *s,char *t) /*char s[],char t[]*/ {while(*t!=0) /*while(*t)*/ {*s=*t;s++;t++;} /* *(s++)=*(t++) */ *s='\0'; } void main() {char *str2;char str1[80]; str2=“welcome“; str_cpy(str1,str2); puts(str1); }
第8章 指针 8. 4 指针数组 由指针构成的数组。定义形式为: 类型标识符 *指针变量名[ ] ; 例如: char *p[ 13] ; p是一个有13个元素的数组,每个元素都是指向char类型的指针。 *p[i]可存取一个字符; p[i]可存取一个字符串。 当处理长度不等的字符串时,数组指针很方便。 返回章目录
第8章 指针 指针数组例1 #include <stdio.h> void main( ) {int i; int a=10, b=8; int *p1=&a,*p2=&b; int *x[2]; x[0]=p1,x[1]=p2; printf("*x[0]=%d\n",*x[0]); printf("*x[1]=%d\n",*x[1]); }把一群指针纳入数组进行管理 返回章目录
第8章 指针 指针数组例2 void main( ) {int i; int a[]={1,2,3}; int b[]={3,4,5}}; int *p[2]; /*p 是数组,元素是指针*/ p[0]=a;p[1]=b; printf("%d,%d,%d\n",*p[0],*(p[0]+1),*(p[0]+2)); printf("%d,%d,%d\n",*p[1],*(p[1]+1),*(p[1]+2)); } 返回章目录
第8章 指针 指针数组例3 void main( ) {int n; char *day-name( ); scanf(“%d”,&n); printf(“%d day:%s\n”,n,day-name(n)); } char *day-name(int n) {char *name[ ]={“illegal day”,”Mon”,”Tues”,”Wen”,”Thurs”, ”Friday”,”Sat”,”Sun”}; return((n<1|n>7)?name[0]:name[n]);| }函数返回一个指向包含第N天名字的字符串的指针。 name指针数组存储字符串列表。各串不等,由系统计数。
第8章 指针 指针数组例4 while(n--) { printf("%s",digt[x[n]]); printf("%s",dw[n]); } } #include <stdio.h> void main() /*整数人民币转换,不完善*/ { char *digt[]={" ","一","二","三","四","五","六","七","八","九"}; char *dw[]={"元","十","百","千","万"}; int m; int n=0,x[5]; scanf("%d",&m); while(m!=0) { x[n]=m%10; /*printf("%d\t",x[n]); */ m=m/10; n++; }
第8章 指针 8.5 指针与函数 8.5.1 指向函数的指针 指向函数的指针叫做函数指针。一个函数在编译时被分配给一个入口地址,这个入口地址称为函数的指针。可以定义一个指向函数的指针变量,将函数入口地址赋予指针变量,然后通过指针变量调用此函数。 指向函数的指针变量定义形式为: 类型标识符 (*指针变量名)( ) ; ↑ 函数返回值的类型 例如: int (*p)( ) ; P表示一个指向函数的指针,P指向的函数返回整型数据。 返回章目录
第8章 指针 而 int *p( ) ; 表示p是一个函数,返回整型指针的函数。前者是指针,后者是函数。函数指针可用来传递函数。 void main( ) {int (*pi)( int x); int prnx(int x); pi=prnx; /*不加 ( )*/; (*pi)(123); } prnx(int x ) { printf("%d\n",x); } 返回章目录
第8章 指针 例2: 由用户指定分别求x2-2和 x3-2x+5的值 double f1(double x ) {return (x*x-2);} double f2(double x ) { return (x*x*x-2*x+5); } void main( ) {int i;double x; double (*fp)(double); scanf("%d%lf",&i,&x); if(i==1) fp=f1; else fp=f2; printf("f(x)=%lf ",(*fp)(x)); }
第8章 指针 8.5.2 返回指针的函数 例: #include <stdio.h> void main( ) {int i; int *p; int *f(int x,int y); p=f(10,8); printf("max=%d\n",*p); } int *f(int x,int y) { int *q; if(x>y) q=&x; else q=&y; return(q); }
第8章 指针 8.6 指针的指针称二级指针。即一个指针存放另一指针的地址。 例: #include <stdio.h> void main() { int a=3; int *p1=&a; int **pp; pp=&p1; printf("**p=%d\n",**pp); printf("*p1=%d\n",*p1); }
第8章 指针 8.7 指针与二维数组 二维数组中: a+i,a[i],*(a+i),&a[i],&a[i][0] 它们都表示地址,且地址值是相等的,但指针类型不同。 a+i和&a[i]指向行,表示第i行首地址; a[i]和*(a+i)用于指向列,表示第i行第0列元素地址。 a[i]+j和*(a+i)+j表示第i行第j列元素地址,见表8-1。
第i行j列元素地址 第i行j列元素值 a[i]+j *(a[i]+j) *(a+i)+j *(*(a+i)+j) &a[i][j] a[i][j] 第8章 指针 表8-1 第i行第j列元素地址及其元素值
第8章 指针 指针与二维 数组例: #include <stdio.h> void main() {int a[2][3]={{1,2,3},{4,5,6}}; int *p=a; printf("a=%d,a[0]=%d,&a[0]=%d,p=%d\n",a,a[0],&a[0],p); printf("*a=%d,**a=%d,*a[0]=%d,*p=%d\n",*a,**a,*a[0],*p); printf("a[1]=%d,a+1=%d\n",a[1],a+1); printf("*a[1]=%d,*(a+1)=%d\n",*a[1],*(a+1)); printf("a[0]+1=%d,p+1=%d\n",a[0]+1,p+1); printf("*(a[0]+1)=%d,*(p+1))=%d\n",*(a[0]+1),*(p+1)); printf("*(p+5)=%d,*(*(a+1)+1))=%d\n",*(p+5),*(*(a+1)+1)); }
第8章 指针 说明: a指向第0行首址,即&a[0] a+1指向第1行首址,即&a[1] a+i指向第i行首址,即&a[i] *a指向0行0列首址a[0][0] *(a+1)指向1行0列a[1][0] *(a+i)指向i行0列a[i][0] *(a+i)+j,a[i]+j指向a[i][j] *(*(a+i)+j),*(a[i]+j)即a[i][j] 从值上看:a 和*a, a+1和*(a+1)相等。 但a+1 与 *a+1不同。前者走1行,后者走1列。 上例中,a指针加1跨度大,p和a[i]跨度小
第8章 指针 8. 8 main()函数的参数 main(int agrc,char *argv[ ]) argc是整型数,表示命令行参数个数,命令名为第一个参数,故 argc至少为1。 argv是指向命令行参数(含命令名)字符串的指针数组。argv[0], argv[1], argv[2]分别指命令名,第2参数,第3参数. 例: void main(int agrc,char *argv[ ] ) {int i; for(i=1;i<argc;i++) printf(“%s%c”,argv[i], (i<agrc-1)? ’ ‘ : ’\n’ ); }
第8章 指针 main()函数的参数 例: void main(int agrc,char *argv[ ]) {int i,n; n=agrc; for(i=0;i<n;i++) printf(“%s”,argv[i] ); } 返回章目录
第8章 指针 指针小结 定义 意义 int i; 整型变量 int *p; 指向整型数据的指针 int *p[n]; 由n个指向整型数据的指针组成的指针数组 int (*p)[n]; 指向n个整型数据的数组的指针 int p( ); 返回整型数据的函数 int *p( ); 返回整型指针的函数 int (*p)( ); 指向整型函数的指针(函数指针)