340 likes | 470 Views
指针. 本章主要内容. 指针的含义 指针使用 不同类型指针的区别 指针与数组的关系 动态单元分配 复杂指针 ( 选学 ) 二维数组的地址 指针数组 指针的指针 数组指针. 指针的含义. char a; a 与 &a 什么类型变量保存 &a. 理解指针的含义. 指针与指针的指针. 指针的初始化. #include "stdio.h" void main() { int a,*p=&a;/* 初始化给 p 赋值 &a, 正确* / int b,*q=b;/* 初始化,类型不匹配错误* /
E N D
本章主要内容 • 指针的含义 • 指针使用 • 不同类型指针的区别 • 指针与数组的关系 • 动态单元分配 • 复杂指针(选学) • 二维数组的地址 • 指针数组 • 指针的指针 • 数组指针
指针的含义 • char a; • a与&a • 什么类型变量保存&a
指针的初始化 • #include "stdio.h" • void main() • { int a,*p=&a;/*初始化给p赋值&a,正确*/ • int b,*q=b;/*初始化,类型不匹配错误*/ • p=a;/*赋值语句,类型不匹配错误*/ • p=&a;/*赋值语句,正确*/ • *p=a;/*赋值语句,正确*/ • }
指针的声明与使用举例-1 • #include "stdio.h" • void main() • { int a,b,*p; • a=20;b=30; • p=&a;*p=50; • printf("a=%d,b=%d\n",a,b); • p=&b; scanf("%d%d",&a,p); • printf("a=%d,b=%d\n",a,b); • }
指针使用举例-2 • #include "stdio.h" • void main() • { char a[10]="abcd",*p=a; • puts(p); • *p='A'; • puts(p); • printf("%c,%s\n",*p,p); • scanf("%s",p); • puts(a); • }
指针使用举例-3 • #include <iostream.h> • void main(){ • int a,b,*pa=&a,*pb=&b,t,*pt; • cin>>a>>b;//输入20 30 • //比较并理解这两行有何不同,同时只使用一行 • if(*pa<*pb){t=*pa,*pa=*pb,*pb=t;} • //if(*pa<*pb){pt=pa;pa=pb;pb=pt;} • cout<<*pa<<","<<*pb<<","<<a<<","<<b<<endl; • }
使用指针注意事项 • 有声明:int a=2,*p;下面哪条语句正确 • *p=a; • p=&a; • 有声明:char *p;下面哪条语句正确 • strcpy(p,”ABC”); • p=“ABC”; • scanf(“%s”,p);
不同类型指针含义 • //运行程序: • #include <stdio.h> • void main() • { char *cp,c[10]; • short int *sp,s[10]; • long *lp,l[10]; • cp=c;sp=s;lp=l; • printf("%p,%p;%p,%p\n",&c[0],&c[1],cp,cp+1); • printf("%p,%p;%p,%p\n",&s[0],&s[1],sp,sp+1); • printf("%p,%p;%p,%p\n",&l[0],&l[1],lp,lp+1); • } • 分析: • //运行程序可以看出,不同类型指针,步长不同,同是加1操作,char 指针变化1,short 指针变化2,long指针变化4,正好是一个本类型单元占据的字节数 • //指针加1与数组下标加1地址相对应
指针与数组之间的关系 • 从前面很多例子可以看出,int a[10];数组名a中保存着数组的首地址,因此也可以用 *a *(a+i)形式访问数组元素 • 指针与数组相同点: • 指针与数组保存的都是地址值,所以在C语言中,可以互换访问方式,*(p+i) p[i] 两种表达形式是完全相同的 • 指针与数组不同点: • 数组是地址常量,不能改变自身的值,如:int a[10];执行a++或a=p都是错的 • 指针是地址变量,可以随时改变自身的值,但是,指针没有分配保存目标类型的单元,必须指向已分配单元时才能使用,如: • int *p;*p=20;(错) int a,*p=&a;*p(对)
指针与数组 • #include <iostream.h> • void main(){ • int a[10]={11,22,33,44,55,66,77,88,99,100},*p,i; • p=a;//p=&a[0]; • for(i=0;i<10;i++)cout<<a[i]<<","; • //a[i]替换成下列形式:*a,*(a+i),*(p+i),*p++,p[i], • //错误形式 *a++; • cout<<endl; • p=&a[3]; • for(i=0;i<10;i++)cout<<p[i]<<","; • cout<<endl; • }
指针与数组的区别 • #include <stdio.h> • void main(){ • char a[]="ABCD";/*给a数组填充字符串"ABCD" 正确*/ • char *p="EFGH";/*让p获得字符串"EFGH"的首地址 正确*/ • a++;/*试图改变地址常量 错误*/ • p++;/*改变指针 正确*/ • a="abcd";/*试图改变地址常量 错误*/ • p="efgh";/*改变指针,让p获得字符串”efgh”的首地址 正确*/ • }
指针与字符串举例1 • #include "stdio.h" • void main() • { char a[]="ABCDEFG",*p=a; • while(*p)puts(p++); • }
指针与字符串举例2 • #include "stdio.h" • #include "string.h" • void main() • { char a[]="ABCDEFG"; • char *p,*q,t; • p=a; • q=a+strlen(a)-1; • while(p<q){ • t=*p;*p=*q;*q=t; • p++;q--; • } • puts(a); • }
stdlib.h提供的malloc函数 • 分配函数格式:void * malloc(int size) • 释放函数格式:free(首地址指针) • 举例: • int *p; p=(int *) malloc(10*sizeof(int));……free(p); • 说明: • malloc函数返回void指针,因此,如果需要某种类型指针,需要强制类型转换 • 函数参数为要求分配字节数,需要自己计算 • 使用结束后要用free函数释放, 否则无法再被使用 • 在释放前不要改变首指针的值,否则这块内存会成为内存中的隐藏碎片,无法再使用
stdlib.h提供的calloc函数 • 分配函数格式:void * calloc(int n,int size) • 释放函数格式:free(首地址指针) • 举例: • int *p; • p=(int*)calloc(10,sizeof(int)); • …… • free(p);
malloc举例 • #include "stdio.h" • #include "stdlib.h" • void main() • { int *p,*q,i; • p=(int *)malloc(10*sizeof(int)); • for(i=0;i<10;i++)scanf("%d",&p[i]);/*改为*p++则失去首地址*/ • q=p+9; • for(i=0;i<10;i++)printf("%d ",*q--); • printf("\n"); • free(p); • }
使用C++运算符new • 分配指令格式: new 类型名 • 释放指令格式:delete 指针 • #include <iostream.h> • void main() • { int *p,*q; • p=new int; • q=new int[10]; • delete p; • delete q; • }
辨别P++,*p++,(*P)++,*(P++)++*p,*++p • #include "iostream.h" • void main() • { int a[2],*p; • cout<<"array add:"<<a<<endl; • a[0]=1;a[1]=10;p=a; • *p++;cout<<"p="<<p<<" value:"<<*p<<" a[0]="<<a[0]<<" a[1]="<<a[1]<< endl; • a[0]=1;a[1]=10;p=a; • (*p)++;cout<<"p="<<p<<" value:"<<*p<<" a[0]="<<a[0]<<" a[1]="<<a[1]<< endl; • }
复杂指针 (选学)
二维数组中的地址 • #include <iostream.h> • void main(){ • int a[3][4],i,j; • for(i=0;i<3;i++){ • for(j=0;j<4;j++) • cout<<&a[i][j]<<"\t"; • cout<<endl; • } • cout<<endl; • for(i=0;i<3;i++)cout<<a[i]<<"\t"<<a[i]+1<<endl; • cout<<endl; • cout<<a<<"\t"<<(a+1)<<endl; • }
二维数组中的地址 • 如有声明 int a[3][4]下面表达式的含义 • #include <iostream.h> • void main(){ • int a[3][4],i,j; • for(i=0;i<3;i++){ • for(j=0;j<4;j++){ • a[i][j]=i*1000+j*100; • cout<<&a[i][j]<<":"<<a[i][j]<<"\t"; • } • cout<<endl; • } • cout<<"*a\t"<<*a<<endl; • cout<<"*(a+1)\t"<<*(a+1)<<endl; • cout<<"*a+1\t"<<*a+1<<endl; • cout<<"**a\t"<<**a<<endl; • cout<<"*(*(a+0)+0)\t"<<*(*(a+0)+0)<<endl; • cout<<"**a+1\t"<<**a+1<<endl; • cout<<"*(*a+1)\t"<<*(*a+1)<<endl; • cout<<"**(a+1)\t"<<**(a+1)<<endl; • cout<<"*(*(a+1)+1)\t"<<*(*(a+1)+1)<<endl; • cout<<"*(*(a+1)+5)\t"<<*(*(a+1)+5)<<endl; • cout<<"*a[2]\t"<<*a[2]<<endl; • cout<<"(*a)[2]\t"<<(*a)[2]<<endl; • cout<<"(*a+1)[2]\t"<<(*a+1)[2]<<endl; • cout<<"(*(a+1))[2]\t"<<(*(a+1))[2]<<endl; • cout<<"*a[2]+1\t"<<*a[2]+1<<endl; • }
指针数组 • 指针数组是连续的地址单元,如int *b[10];声明了10个指针,而b本身是和指针的的指针同类型的地址量,举例: • #include <iostream.h> • void main() • { int a[10][3],*s,*b[10],i,j; • s=&a[0[0]; • for(i=0;i<30;i++)*s++=i; • for(i=0;i<10;i++)b[i]=a[i]; • for(j=0;j<3;j++) • { for(i=0;i<10;i++)cout<<*b[i]++<<" "; • cout<<endl; • } • }
指针的指针 • 指针的指针是保存指针单元地址的单元 • #include <iostream.h> • void main() • { int a,*p,**pp; • a=20; • p=&a; • pp=&p;//or *pp=p; • **pp=50; • cout<<a<<endl; • }
指针的指针举例 • #include <stdio.h> • void main(){ • int **pp; • int *p,a=1; • p=&a;/*p指向a*/ • pp=&p;/*pp指向p*/ • printf("a=%d\n",**pp);/*输出a的内容*/ • int b[2]={2,3}; • p=b;/*p指向b[0]*/ • p++;/*p指向b[1]*/ • printf("b[1]=%d\n",**pp);/*输出b[1]的内容*/ • int c[3][2]={4,5,6,7,8,9},*pa[3]; • pa[0]=c[0];pa[1]=c[1];pa[2]=c[2];/*指针数组获得a[i]*/ • pp=pa;/* pp指向指针数组首地址*/ • printf("c[0][0]=%d\n",**pp);/*输出a[0][0]*/ • printf("c[0][1]=%d\n",*(*pp+1));/*输出a[0][0]*/ • printf("c[1][0]=%d\n",**(pp+1));/*输出a[0][0]*/ • printf("c[1][1]=%d\n",*(*(pp+1)+1));/*输出a[0][0]*/ • }
数组指针 • 从前面可以看出,int a[5][10]; a是一个特殊的地址,a保存着a[0]、a[1]、a[2]、a[3]、a[4]一维数组的首地址,每加1,则指向下一个数组,要保存这种地址需要的变量就是数组指针 • 声明举例:int (*p)[10]; • p是指向每个对象都是拥有10个整形单元数组 • 对比:int *a,(*b)[10]; • a指向的对象是4个字节的整形单元 • b指向的对象是40个字节的数组
复杂指针综合举例 • #include <iostream.h> • void main(){ • int a[3][4],i,j; • int *p[3];//指针数组,定义三个整型指针 • int (*q)[4];//数组指针,定义一个指乡数组的指针 • int **r;//定义一个指向整型指针的指针 • for(i=0;i<3;i++) • for(j=0;j<4;j++)a[i][j]=i*10+j; • cout<<*(a[0]+5)<<endl; • p[0]=a[0];//a[0],*p[0]都是整型指针 • for(i=0;i<12;i++)cout<<*p[0]++<<" "; • cout<<endl; • q=a;//a指向[3]数组的指针 • for(i=0;i<3;i++)cout<<**q++<<" "; • cout<<endl; • p[0]=a[0];p[1]=a[1];p[2]=a[2]; • for(i=0;i<3;i++)cout<<p[i]<<" ";//输出连续三个整型指针的地址 • r=&p[0];//r指向指针数组首地址 ,,,r=&a[0]将产生错误 • cout<<endl; • for(i=0;i<3;i++)cout<<*r++<<" ";//输出连续三个整型指针的地址 • cout<<endl; • r=&p[0];//r指向指针数组首地址 • for(i=0;i<3;i++)cout<<* *r++<<" ";//输出连续三个整型指针的地址所指的整数 • cout<<endl; • //r=a;//worng • //r=q;//wrong • }