资源预览内容
第1页 / 共57页
第2页 / 共57页
第3页 / 共57页
第4页 / 共57页
第5页 / 共57页
第6页 / 共57页
第7页 / 共57页
第8页 / 共57页
第9页 / 共57页
第10页 / 共57页
亲,该文档总共57页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
指 针6.2 指针的概念指针的概念6.3 指针与数组指针与数组6.4 字符串的指针字符串的指针6.5 指针数组和指向指针的指针指针数组和指向指针的指针6.2.1 地址与指针的概念地址与指针的概念 6.2.2 指针的定义与引用指针的定义与引用 6.2 指针的概念指针的概念指针的概念指针的概念指针是变量存放地址的变量这个地址可以是变量的地址,也可以是复杂数据类型的地址,如数组,结构体等,也可以是函数的地址。指针变量存放了哪个变量的地址就称该指针指向了这个变量。内存地址内存地址1、变量与地址 程序中: int i; float k; 内存中每个字节有一个编号-地址.2000200120022005内存02003ik 编译或函数调用时为其分配内存单元变量是对程序中数据存储空间的抽象2、数组与地址 地址内存单元整型数组元素a0整型数组元素a1整型数组元素a2123300030013002300330043005数组与地址对照表 数组名 数据类型 长 度 首地址 a 整型整型 3 3000程序中:int a3=1,2,3;指针与指针变量指针与指针变量 .2000200420062005整型变量i10变量i_pointer200120022003指针:一个变量的地址指针变量:专门存放变量地址的变量叫2000指针指针变量 变量的内容 变量的地址指针变量变量变量地址(指针)变量值指向地址存入指针变量寻址寻址访问内存单元称为寻址。直接寻址:通过变量名对内存单元进行存取。间接寻址:通过指针变量间接存取。 指针变量的定义、初始化和引用指针变量的定义、初始化和引用 ( (一一) )、指针变量的定义和初始化、指针变量的定义和初始化 数据类型数据类型 * *指针变量名指针变量名1=初值初值1,; 指针变量的定义和初始化格式 例:指针变量的定义和初始化。 int a; int *p=&a; float f1,f10,*p1=&f1,*p2=f; int* p; int*p; int * p; int* p, i; 注意指针的指向编译器不识别没有明确指向的指针。但使用这样的指针可能导致错误。( (二二) )、指针变量的引用方式、指针变量的引用方式 1、直接引用指针变量名使用格式为:指针变量表达式指针变量表达式。这个表达式必须是地址型表达式例如:int i,*p_i, *q; p_i=&i;q=p_i;需要用到地址时,可以直接引用指针变量名。例如:int i,j,*p=&i; scanf(“%d,%d”,p,&j);2、通过指针变量来引用所指向的变量使用格式为:* 指针变量名。在程序中“* 指针变量名”代表它所指向的变量。例如:int i=1,j=2,k,*p=&i; k=*p+j;( (三三) )、取地址运算符与指针运算符、取地址运算符与指针运算符 对象数对象数名称名称运算符运算符运算规则运算规则运算对象运算对象 运算结果运算结果结合性结合性 单目单目 前缀前缀取地取地址址 &取运算对取运算对象的地址象的地址变量或数变量或数组元素组元素对象的地对象的地址址 单目单目 前缀前缀指针指针 *取所指向取所指向的变量或的变量或数组元素数组元素指针变量、指针变量、变量或数变量或数组元素的组元素的地址地址指针变量指针变量所指向的所指向的变量或数变量或数组元素组元素自右向自右向左左 取地址运算符和指针运算符的运算对象、运算规则、结合性如表所示。 &和和*优先级别优先级别 &、*和自增、自减等单目运算符是同级别的 所有单目运算符的结合性均为自右向左 例如,设有变量a、指针变量pa,且pa已经指向a。*&a 正确的。相当于“*(&a)”,&a是变量a的地址,*(a地址)代 表变量a。&* a 错误的。相当于“&(*a) ”,因为a不是指针变量, 所以* a不正确。 *&pa 正确的。相当于“*(&pa)”, &pa是pa的地址,*(pa地址) 代表指针变量pa。&*pa 正确的。相当于“&(*pa)”,*pa代表变量a,&(变量a)代 表a的地址。 混合使用运算符混合使用运算符例:例:用指针变量按从小到大的顺序输出三个整数。main() int a,b,c,*pa=&a,*pb=&b,*pc=&c,*p; scanf(“%d,%d,%d”,pa,pb,pc); if (*pa*pb) p=pa;pa=pb;pb=p; if (*pa*pc) p=pa;pa=pc;pc=p; if (*pb*pc) p=pb;pb=pc;pc=p; printf(“%d=%d=%dn”,*pa,*pb,*pc); 6.3 指针与数组6.3.1 指向一维数组的指针6.3.2 指向多维数组的指针指向一维数组的指针指向一维数组的指针int a10;int *p;p=&a0; /p=a;这样指针p就指向了一维数组a 指向一维数组的指针变量的使用指向一维数组的指针变量的使用 处理数组元素的关键是引用数组元素,引用数组元素的方法与指针指向数组的方式有关: 当指针变量指向数组首地址时,引用数组元素的方法如下:引用“数组元素0” * (指针变量0) 或 * 指针变量引用“数组元素i” * (指针变量i)1、用指针处理数组元素这里的“指针变量1”代表同数组的下一个元素 当指针变量指向下标为i的数组元素时,引用数组元素的方 法如下:引用“数组元素i” * (指针变量0) 或 * 指针变量引用“数组元素i-k” * (指针变量-k)引用“数组元素i+k” * (指针变量k) 当指针变量指向首地址后,对下标为i的数组元素引用一共 有下列四种方法:* (指针变量i) * (数组名i) 指针变量i 数组名i 方法1,2引用数组元素的方法使用了“指针运算符”,称为“指针法”;方法3,4引用数组元素的方法使用了“下标运算符()”称为“下标法下标法”。注意:注意: 指针变量是存放地址这种数据类型的变量,可以按照变量的处理方式对其进行运算;而数组名仅仅是一个地址常量,只能按照常量的方式进行处理。2、指向一维数组的指针变量的运算 当指针变量已指向数组后,对指针变量可以进行算术和关系运算。(1)指针变量和整数的算术运算。 对指针变量进行算术运算的规则如下:指针变量整数 “指针变量中的地址整数*指针变量类型占 用单元数”对应的地址指针变量整数 “指针变量中的地址整数*指针变量类型占 用单元数”对应的地址指针变量 “指针变量中的地址指针变量类型占用单元 数”对应的地址,此后,指针变量将指向下一 个数组元素。指针变量 “指针变量中的地址指针变量类型占用单元 数”对应的地址,此后,指针变量将指向上一 个数组元素。指针变量 “指针变量中的地址”对应的地址(因为是后缀 减1运算符),此后,指针变量将指向上一个 数组元素。指针变量 “指针变量中的地址”对应的地址(因为是后缀 增1运算符),此后,指针变量将指向下一个 数组元素。 上述运算规则组成的式子称为表达式表达式,这种表达式的类型是“地址型”,所以上述规则组成的表达式常称为“地址型表达式”或“指针型表达式”,简称为“指针表达式”。例如:设定义了整型数组a10,整型指针变量pa,且执行了pa=a。假定数组a的首地址为2000。请看下列的表达式及其运算结果:执行papa5后 pa指向数组元素a5,pa的地址值将为 20005*22010,其中的“2”是整型数据 占用的单元数;再执行pa后 pa将指向数组元素a4,pa的地址值将为 20101*22008。注意:注意:对代表地址常量的数组名不能进行增1减1的算术运算,+a、a+、-a、a-、a=a+5、a=a-5都是错误的。(其中a为数组名)(2)指针变量和指针变量的减法运算指针变量和指针变量的减法运算规则如下: 指针变量指针变量1指针变量指针变量2 要求这两个指针变量必须指向同一个数组,否则不能进行减法运算。运算 结果为它们所指向的数组元素下标相差的整数。 例如,定义了数组a和同类型的指针变量p1、p2。其中p1指向数组元素a2;p2指向数组元素a6。p1p2 结果为整数4p2p1 结果为整数4 当两个指针变量的值(地址值)满足关系运算时,结果为1(真)否则结果为0(假)。 例如,定义了数组a和同类型的指针变量p1、p2;使p1指向数组元素a2;p2指向数组元素a3。下列关系表达式及其运算结果: p1p2 结果为1(真)。 p1p2 结果为0(假),注意是后缀。 p2p1 结果为1(真),注意是前缀。 p1a 结果为0(假),a是地址常量。 p1&a9 结果为1(真), &a9是地址常量。 p2=a3 结果为1(真),a3是地址型表达式, 代表a3的地址。(3)指针变量的关系运算。对指针变量进行关系运算对规则如下: 指针变量指针变量1 关系运算符关系运算符 指针变量指针变量2例:输入10个整数存入一维数组,从中查找某个整数(该数从键盘上读取),查到则输出其是第几个数,查不到则输出“Not Find!”。要求用指针法处理。程序清单如下: main() int a10,*p=a,x,n,flag=0; for (;pa+10;p+) scanf(“%d”,p); scanf(“%d”,&x); for (n=1,p=a;pa+10;p+,n+) if (*p=x) flag=1;break; if (!flag) printf(“Not Find!n”); else printf(“%dn”,n); 3、关于使用“指针法”处理一维数组元素的下标越界问题 C语言对用“指针法”引用数组元素时,对下标是否越界也不作检查,即允许下标越界。例如,定义了整型数组a10,并使同类型的指针变量p指向了数组a的首地址的首地址。则下列对a数组的元素引用都是允许的:*(p-1) 代表数组元素a0前面2个单元中存放的数据 (看成整数)*(p+10) 代表数组元素a9后面2个单元中存放的数据 (看成整数) 虽然C语言允许处理数组元素时下标可以越界,但在程序中要尽量避免。当出现下标越界的情况,如果你使用的是数组元素值,显然这个值不知为何值;如果你是将某个值存入该数组元素,结果将会破坏对应内存单元中原来的值,使得后面程序运行时,结果不正确,甚至出现预料不到的问题,而这样的错误很难查找。 指向二维数组的指针变量的使用指向二维数组的指针变量的使用 1、指针变量指向二维数组的某个元素 当指针变量指向二维数组的某个元素时,利用指针变量来处理该数组元素和处理一维数组元素的方法相同。(1)让指针变量指向二维数组的某个元素的方法。 用初始化方式的格式为:类型 *指针变量&数组名下标1下标2 用赋值方式的格式为:指针变量&数组名下标1下标2(2)二维数组元素的引用方法。 当指针变量已指向二维数组元素后,引用该数组元素的方法 是:* 指针变量例1:输入2行3列的矩阵元素后,存入二维数组。再按行列格式输出。 main() int a23,*p; int i,j; for (i=0;i2;i+) for (j=0;j3;j+) p=&aij; scanf(“%d”,p); for (i=0;i2;i+) printf(“n”); for (j=0;j3;j+) p=&aij; printf(“%10d”,*p); 程序如下:2、指针变量指向二维数组的首地址 当指针变量指向二维数组的首地址时,也可以处理数组中的任何一个元素。(1)让指针变量指向二维数组首地址的方法。 使用初始化或赋值方式都可以使指针变量指向二维数组的首地址。使用初始化方式有两种:类型类型 * 指针变量二维数组名指针变量二维数组名0类型类型 * 指针变量指针变量&二维数组名二维数组名00使用赋值方式有两种:指针变量二维数组名指针变量二维数组名0指针变量指针变量&二维数组名二维数组名00(2)二维数组元素的引用方法。 当指针变量已指向二维数组的首地址后,引用该数组第i行第j列的元素的方法是: *(指针变量(指针变量i*列数列数j)例如:已定义了二维数组a23,其2行3列元素在内存中排列顺序如下: a00 a01 a02 a10 a11 a12 如果定义指针变量p并且指向数组a的首地址,则这些元素的地址和引用方法如下:元素元素元素地址元素地址元素引用元素引用 a00 p+0*3+0=p *(p+0*3+0)=*(p) a01 p+0*3+1=p+1 *(p+0*3+1)=*(p+1) a02 p+0*3+2=p+2 *(p+0*3+2)=*(p+2) a10 p+1*3+0=p+3 *(p+1*3+0)=*(p+3) a11 p+1*3+1=p+4 *(p+1*3+1)=*(p+4) a12 p+1*3+2=p+5 *(p+1*3+2)=*(p+5)例2:重编例1,要求使用指向二维数组首地址的指针变量处理二维数组元素。程序清单如下:main() int a23,*p=a; int i,j; for (i=0;i2;i+) for (j=0;j3;j+) scanf(“%d”,p+i*3+j); for (i=0;i2;i+) printf(“n”); for (j=0;j3;j+) printf(“%10d”,*(p+i*3+j); 3、指针变量指向二维数组中某个一维数组(1)让指针变量指向二维数组中某个一维数组的方法。 如果你希望将指针变量指向二维数组中某个一维数组,首先要按下列格式定义一个指针变量: 类型(类型(* 指针变量)指针变量)m 其中的m是对应二维数组的列长度 然后再用初始化或赋值方式将该指针变量指向二维数组的首地址类型(类型(* 指针变量)指针变量)m二维数组名二维数组名 (初始化)指针变量二维数组名指针变量二维数组名 (赋值) 二维数组中第i行对应的一维数组首地址可以用下列表达式来获得: * (指针变量(指针变量i)实际上等价于 指针变量指针变量i使用这种指针变量,需要注意以下几点:使用这种指针变量,需要注意以下几点: 定义这种指针变量时,圆括号不能丢。 定义这种指针变量时,m必须是整型常量表达式,并且其值 要等于希望指向的一维数组的长度。 定义这种指针变量后,赋初值或赋值时应该赋予列长度为m 的二维数组首地址,然后用表达式方式来获得二维数组中某 个一维数组的首地址。(2)二维数组元素的引用方法。 当某个指向一维数组的指针变量已指向对应二维数组的首地址后,就可以用像处理一维数组元素的方式来处理这个二维数组中已指向的一维数组。具体的格式如下: 数组元素地址 *(指针变量行下标)列下标(指针变量行下标)列下标 数组元素引用 *(*(指针变量行下标)列下标)(指针变量行下标)列下标) 例如语句“int a25,(*p)5=a;”定义了二维数组a25和指向具有5个元素的一维数组指针变量p,并且使p指向二维数组a的首地址。则对应二维数组中2个一维数组的首地址如下:二维数组中的一维数组用指针变量表示对应一维数组 的首地址a0a1*(p0)*(p1)二维数组元素的引用格式如下:数组元素数组元素 a00 a01 a02 a03 a04 引用格式引用格式 *(*(p+0)+0) *(*(p+0)+1) *(*(p+0)+2) *(*(p+0)+3) *(*(p+0)+4)数组元素数组元素 a10 a11 a12 a13 a14 引用格式引用格式 *(*(p+1)+0) *(*(p+1)+1) *(*(p+1)+2) *(*(p+1)+3) *(*(p+1)+4)或者或者 p00 p01 p02 p03 p04 6.4 字符串的指针字符串的指针 字符串有:常量字符串 例如:“ABC”变量字符串 例如:char c“abc”; 无论哪一种字符串,都可以用字符型指针变指向它,以后也可以用字符型指针来处理这个字符串或字符串中的单个字符。1、如何将指针变量指向字符串常量 第一种方法是给指针变量初始化的方式,格式为 char * 指针变量指针变量“字符串常量字符串常量”; 假定要求字符型指针变量p指向字符串常量“abcd”;可以采用下列两种方式: 第二种方法是先定义一个字符型指针变量,然后通过赋值方式,其格式为“指针变量字符串常量指针变量字符串常量”。方法一 char *p=“abcd”;方法二 char *p=NULL;p=“abcd”; 可以用赋值方式使指针变量指向字符串常量,但是不允许将字符串常量赋值给字符型数组。例如,下列的程序段是错误的:char a10;a=“abcd”; C语言允许在同一个程序中,使同一个字符型指针变量先后指向不同的字符串常量,例如下列的程序段是正确的: char *pa=NULL; pa=“12345678”; pa=“abcd”;2. 指向存放字符串的字符数组的指针变量的使用 当一个字符型指针变量已指向某个字符串常量,就可以利用指针变量来处理这个字符串。处理的方式主要有两种:(1)处理整个字符串 输出字符串输出字符串 printf(“%s”,指针变量指针变量); 输入新的字符串代替原字符串输入新的字符串代替原字符串 scanf(“%s”,指针变量指针变量);(2)处理字符串中的单个字符 第第i个字符的表示方法个字符的表示方法 * (指针变量指针变量i)6.5 6.5 指针数组和指向指针的指针指针数组和指向指针的指针 指针数组:若某个数组被定义为指针类型,则该数组为指针数组。指针数组中的每个元素都相当于一个指针型变量,只能存放地址型数据。指向指针的指针:若定义的某个指针型变量专门用来存放其它指针变量的地址,则该指针变量为指针的指针,也叫二级指针二级指针。1、指针数组的定义指针数组的定义 需要注意指针数组是指针类型的,对其元素所赋的值必须是地址值。格式 存储类型存储类型 数据类型数据类型 * 指针数组名指针数组名长度长度初值初值;功能 定义指向“数据类型”变量或数组的指针型数组,同时给 指针数组元素赋初值。这些指针变量具有指定的“存储 类型”。说明(1)指针数组名是标识符,前面必须有“*”号。(2)在一个定义语句中,可以同时定义普通变量、数组、指 针变量、指针数组。可以给某些指针数组赋初值,而另 一些指针数组不赋初值。(3)定义指针变量时的“数据类型”可以选取任何基本数据类 型,也可以选取其它数据类型。(4)省略“存储类型存储类型”,默认为自动型(auto)。(5)其中的“初值初值”与普通数组赋初值的格式相同,每个初值 通常是“&普通变量名普通变量名”、 “&数组元素数组元素”或“数组名数组名”,对应 的普通变量或数组必须在前面已定义。(6)注意语句中指针型数组的书写格式,不能写成“ (* 数组名)数组名)长度长度”,因为这是定义指向含有“长度”这个 元素的一维数组的指针变量。例如有定义语句“int a,b,c,*p3&a,&b,&c;”2 2、指针数组元素的引用、指针数组元素的引用 引用所指向的普通变量或数组元素 * 指针数组名指针数组名下标下标 对其赋值 指针数组名指针数组名下标下标地址表达式地址表达式 参加运算 (赋值运算) 指针变量指针数组名下标 (算术运算) 指针数组名下标整数 指针数组名下标整数 指针数组名下标 指针数组名下标 指针数组名下标 指针数组名下标(关系运算)指针数组名下标 关系运算符 指针数组名下标 其中,算术运算和关系运算一般只使用于该指针数组元素指向某个数组时。例5:输入5个字符串存入一个二维数组中,然后定义一个指针数组,使其元素分别指向这5个字符串并输出。程序清单如下: main() char s520,*p5; int i; for (i=0;i5;i+) pi=si; for (i=0;i5;i+) scanf(“%s”,pi); for (i=0;i5;i+) printf(“%sn”,pi); 3 3、多级指针的定义和应用、多级指针的定义和应用 在C语言中,把这种指针型变量称为“指针的指针”,意为这种变量是指向指针变量的指针变量,也称多级指针。通常使用的多级指针是二级指针,相对来说,前面介绍的指针变量可以称为“一级指针变量一级指针变量”。二级指针变量的定义和赋初值方法如下:二级指针变量的定义和赋初值方法如下:格式格式 存储类型存储类型 数据类型数据类型 *指针变量名指针变量名初值初值,功能功能 定义指向“数据类型数据类型”指针变量的二级指针变量,同时给 二级指针变量赋初值。说明说明(1)二级指针变量名的构成原则是标识符,前面必须有“* *”号。(2)在一个定义语句中,可以同时定义普通变量、数组、指针 变量、指针数组、二级指针变量等。可以给某些二级指针 变量赋初值,而另一些二级指针变量不赋初值。(3)定义时的“数据类型”可以选任何基本数据类型,也可以选 取以后介绍的其它数据类型。这个数据类型是它将要指向 的指针变量所指向的变量或数组的数据类型。(4)其中的“初值”必须是某个一级指针变量的地址,通常是“ &一级指针变量名一级指针变量名”或“一级指针数组名一级指针数组名”,对应的一级指针 变量或数组必须在前面已定义。例如,有定义语句“int a,b,c,*p1,*p2=&p1;” 二级指针变量还可以通过赋值方式指向某个一级指针变量。赋值的格式如下: 二级指针变量二级指针变量&一级指针变量一级指针变量 当某个二级指针变量已指向某个一级指针变量,而这个一级指针变量已指向某个普通变量,则下列的引用格式都是正确的。 * 二级指针变量 代表所指向的一级指针变量 *二级指针变量 代表所指向的一级指针变量指向的变量 例如,设有定义语句“int a,*p1=&a,*p2=&p1;”,则下列的引用都是正确的:*p1 代表变量a*p2 代表指针变量p1*p2 代表变量a例6:输入5个字符,从中找出最大的字符并输出。要求用字符数组存放这5个字符,用指针数组元素分别指向这5个字符,再用一个二级指针变量指向这个指针数组。程序清单如下: main() char a5,*p5,*q,*max; int i; for (i=0;i5;i+) pi=&ai; for (i=0;i5;i+) scanf(“%c”,pi); max=&p0; q=+p; for (i=1;i5;i+,q+) if (*max*q) max=q; printf(“%cn”,*max); 课堂练习课堂练习指针应用程序设计例指针应用程序设计例题题例1:输入n(不大于20)个单精度数存入一维数组,用指针变量处理数组元素的方式将其逆序存放后输出。n从键盘输入。 main() float a20,x,*pb,*pe; int n,k,i; scanf(“%d”,&n); pb=a; for (i=0;in;i+) scanf(“%f ”,pb+); k=n/2; for (i=0,pb=a,pe=a+n-1;ik;i+,pb+,pe-) x=*pb,*pb=*pe,*pe=x; for (pb=a;pba+n;pb+); printf(“%f ”,*pb); 例2:求35整数矩阵中的最大元素、最小元素、所有元素的平均值。(要求用指向二维数组首地址的指针变量按二维数组排列方式处理二维数组元素。)程序清单如下: main() int a35,*p=a,max,min,i,j; float ave=0.0; for (i=0;i3;i+) for (j=0;j5;j+) scanf(“%d”,p+i*5+j); p=a; max=min=*(p+0*5+0); for (i=0;i3;i+) for (j=0;jmax) max=*(p+i*5+j); if (*(p+i*5+j)min) min=*(p+i*5+j); ave+=*(p+i*5+j); printf(“max=%dn”,max); printf(“min=%dn”,min); printf(“ave=%fn”,ave/15.0); 例3:输入5个字符串,从中找出最大的字符串并输出。要求用二维字符数组存放这5个字符串,用指针数组元素分别指向这5个字符串,用一个二级指针变量指向这个指针数组。程序清单如下: main() char a580,*p5,*q,*max; int i; for (i=0;i5;i+) pi=ai; for (i=0;i5;i+) gets(pi); max=&p0; q=&p1; for (i=1;i5;i+,q+) if (strcmp(*max,*q)0 max=q; puts(*max);
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号