本章主要内容

34
指指

Upload: winter-walton

Post on 30-Dec-2015

34 views

Category:

Documents


5 download

DESCRIPTION

指针. 本章主要内容. 指针的含义 指针使用 不同类型指针的区别 指针与数组的关系 动态单元分配 复杂指针 ( 选学 ) 二维数组的地址 指针数组 指针的指针 数组指针. 指针的含义. char a; a 与 &a 什么类型变量保存 &a. 理解指针的含义. 指针与指针的指针. 指针的初始化. #include "stdio.h" void main() { int a,*p=&a;/* 初始化给 p 赋值 &a, 正确* / int b,*q=b;/* 初始化,类型不匹配错误* / - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 本章主要内容

指针

Page 2: 本章主要内容

本章主要内容• 指针的含义• 指针使用• 不同类型指针的区别• 指针与数组的关系• 动态单元分配• 复杂指针(选学)

– 二维数组的地址– 指针数组– 指针的指针– 数组指针

Page 3: 本章主要内容

指针的含义• char a;• a 与 &a• 什么类型变量保存 &a

声明的类型 变量名 能存储的内容

int a 整数

int * p 整数变量的地址

Page 4: 本章主要内容

理解指针的含义

Page 5: 本章主要内容

指针与指针的指针

Page 6: 本章主要内容

指针的初始化• #include "stdio.h"• void main()• { int a,*p=&a;/* 初始化给 p 赋值 &a, 正确 */• int b,*q=b;/* 初始化,类型不匹配错误 */• p=a;/* 赋值语句,类型不匹配错误 */• p=&a;/* 赋值语句,正确 */• *p=a;/* 赋值语句,正确 */• }

Page 7: 本章主要内容

指针的声明与使用举例 -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);• }

Page 8: 本章主要内容

指针使用举例 -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);• }

Page 9: 本章主要内容

指针使用举例 -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;• }

Page 10: 本章主要内容

使用指针注意事项• 有声明: int a=2,*p; 下面哪条语句正确

– *p=a;– p=&a;

• 有声明: char *p; 下面哪条语句正确– strcpy(p,”ABC”);– p=“ABC”;– scanf(“%s”,p);

Page 11: 本章主要内容

不同类型指针含义• // 运行程序 :

– #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 地址相对应

Page 12: 本章主要内容

图示不同类型指针含义

Page 13: 本章主要内容

指针与数组之间的关系• 从前面很多例子可以看出 ,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( 对 )

Page 14: 本章主要内容

指针与数组• #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;• }

Page 15: 本章主要内容

指针与数组的区别• #include <stdio.h>• void main(){• char a[]="ABCD";/* 给 a 数组填充字符串 "ABCD" 正确 */• char *p="EFGH";/* 让 p 获得字符串 "EFGH" 的首地址 正

确 */• a++;/* 试图改变地址常量 错误 */• p++;/* 改变指针 正确 */• a="abcd";/* 试图改变地址常量 错误 */• p="efgh";/* 改变指针,让 p 获得字符串” efgh” 的首地址

正确 */• }

Page 16: 本章主要内容

指针与字符串举例 1

• #include "stdio.h"

• void main()

• { char a[]="ABCDEFG",*p=a;

• while(*p)puts(p++);

• }

Page 17: 本章主要内容

指针与字符串举例 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);• }

Page 18: 本章主要内容

内存的动态分配

Page 19: 本章主要内容

stdlib.h 提供的 malloc 函数• 分配函数格式 :void * malloc(int size)• 释放函数格式 :free( 首地址指针 )• 举例 :

– int *p; p=(int *) malloc(10*sizeof(int));……free(p);

• 说明 :– malloc 函数返回 void 指针 , 因此 , 如果需要某种类型指针 , 需

要强制类型转换– 函数参数为要求分配字节数 , 需要自己计算– 使用结束后要用 free 函数释放 , 否则无法再被使用– 在释放前不要改变首指针的值 , 否则这块内存会成为内存中的

隐藏碎片 , 无法再使用

Page 20: 本章主要内容

stdlib.h 提供的 calloc 函数• 分配函数格式 :void * calloc(int n,int size)

• 释放函数格式 :free( 首地址指针 )

• 举例 :– int *p;– p=(int*)calloc(10,sizeof(int));– ……– free(p);

Page 21: 本章主要内容

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);• • }

Page 22: 本章主要内容

使用 C++ 运算符 new

• 分配指令格式 : new 类型名• 释放指令格式 :delete 指针

– #include <iostream.h>

– void main()

– { int *p,*q;

– p=new int;

– q=new int[10];

– delete p;

– delete q;

– }

Page 23: 本章主要内容

辨别 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;

• }

Page 24: 本章主要内容

复杂指针

( 选学 )

Page 25: 本章主要内容

二维数组中的地址• #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;• }

Page 26: 本章主要内容

二维数组中的地址

Page 27: 本章主要内容

二维数组中的地址

Page 28: 本章主要内容

二维数组中的地址• 如有声明 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;• }

Page 29: 本章主要内容

指针数组• 指针数组是连续的地址单元 , 如 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;– }– }

Page 30: 本章主要内容

指针的指针• 指针的指针是保存指针单元地址的单元• #include <iostream.h>• void main()• { int a,*p,**pp;• a=20;• p=&a;• pp=&p;//or *pp=p;• **pp=50;• cout<<a<<endl;• }

Page 31: 本章主要内容

指针的指针举例• #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]*/• }

Page 32: 本章主要内容

数组指针• 从前面可以看出 ,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 个字节的数组

Page 33: 本章主要内容

复杂指针综合举例• #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

• }

Page 34: 本章主要内容

复杂指针综合举例