C语言程序设计实用教程陈方第6章_第1页
C语言程序设计实用教程陈方第6章_第2页
C语言程序设计实用教程陈方第6章_第3页
C语言程序设计实用教程陈方第6章_第4页
C语言程序设计实用教程陈方第6章_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

6.1指针与指针变量6.1.1指针在计算机中,内存由一个个具有连续编码的存储单元所组成,即每一个存储单元都具有唯一的、固定的编号,这个编号称为内存单元的地址。如果在程序中定义了一个变量,由于不同的数据类型占据不同字节的存储空间,在编译时,系统就根据程序中定义的变量类型,分配相应的存储空间。例如,对整型变量分配2个字节,对实型变量分配4个字节,对字符型变量分配1个字节,而每一个字节都有一个地址。每个变量的首字节的地址称为该变量的地址。一个变量的地址称为这个变量的指针,指针就是地址。内存中的地址常用十六进制整型数表示。如何查看一个变量的地址呢?可以用取地址运算符“&”来实现。如运行以下程序:main(){inta=26;printf("&a=%x,a=%d\n",&a,a);}可以查看整型变量a的地址(a占2个字节,看到的是它的首字节的地址)和a的值。

6.1.2直接访问和间接访问在C语言的程序中,一般是通过变量名对内存单元进行存取操作的。程序经过编译以后将变量名转换为变量的地址,对变量值的存取都是通过地址进行的。像这种直接按变量地址存取变量值的方式称为“直接访问”。如对以下程序:main(){inta,b,c;a=10;b=16;c=a+b;printf("%d\n",c);}

变量的“间接访问”方式是将变量a的地址存放在另一个称为“指针变量”的变量中,当要读取变量a的值时,先从指针变量中取出a的地址,再从这个地址单元中取出a的值。

6.1.3指针变量的定义和引用如前所述,变量的地址就是变量的指针,存放变量指针(地址)的变量称为指针变量。指针变量的使用和其他变量的使用一样需要“先定义,后使用”。1.指针变量的定义

指针变量不同于其他变量,它是用来专门存放地址的,必须将它定义为“指针类型”。指针变量定义的一般形式为:数据类型*指针变量名其中,“数据类型”说明该指针变量所指向的变量类型,“*”表示所定义的变量是一个指针变量而不是一个普通变量。例如:inta,b,*pa,*pb;pa=&a;pb=&b;定义了整型变量a、b及指针变量pa、pb,且pa、pb是用来指向整型变量的(即用来存放整型变量的地址)。“&”是取地址运算符,pa=&a将变量a的地址存放到指针变量pa中,pb=&b将变量b的地址存放到指针变量pb中。在定义指针变量时可以赋给初值,例如:inta,b,*pa=&a,*pb=&b;

2.指针变量的引用

在定义了一个指针变量并确定了它的指向后,就可以利用它来访问所指向的变量,称为对指针变量的引用。引用指针变量的一般形式为:*指针变量名这里的“*”称为指针运算符,也称为“间接访问”运算符。

[例6-1]

指针变量的引用。程序如下:main(){inta,b,*pa,*pb;pa=&a;pb=&b;a=2;b=4;printf("%d,%d\n",*pa,*pb);*pa=10;*pb=20;printf("%d,%d\n",a,b)}程序运行结果:2,410,20注意:在C语言中,“*”符号目前已出现三种用法,一是乘法符号;二是指针变量定义符;三是指针变量引用符。在上例中,“先定义”指针变量,“后使用”——给它赋值(变量的地址)、引用它。等同于变量a*pa变量a的地址&apa=&a6.2指针运算与其他变量一样,指针也是一种特殊的变量,也有指针运算。其中最常用的运算有:取地址运算&,取值运算*,以及指针加、减运算等。1.取地址运算&取地址运算是指取出运算符&后面的变量在内存中占用的空间的起始地址。因为被指向的变量可能占用多个内存单元,指针并不记录它的所有地址,而只指向它的起始地址。2.取数据运算*与取地址运算符“&”相对应的是取数据运算符“*”,也称指针运算符。取地址运算的操作对象是变量,而取数据运算的操作对象则是指针变量,用于访问某个地址的数据。“*”运算符除作为取数据运算符外,还作为定义指针变量标识符,另外还可作为算术乘法运算符。对于“*”在不同场合的作用,编译器能够根据上下文环境判别其作用。3.指针变量的算术运算

在C语言中,可以通过加减一个整数来移动指针。指针增1运算后指向下一个数据(注意不是下一个字节)的位置,指针减1运算后指向上一个数据的位置。例如:inta,*pa;pa=&a;pa++;在这段程序中,定义pa为指向整型变量的指针变量,则pa++相当于pa=pa+1×2(每个整型变量在内存中占两个字节),即pa++使指针向下移动两个字节指向下一个数据。6.3指针与数组指针与数组关系密切。一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。因此,指针变量可以指向数组和数组元素。数组的指针是数组的起始地址,数组元素的指针是数组元素的地址。使用指针可以对数组进行相关的操作。6.3.1指向一维数组的指针变量C语言规定一维数组的数组名代表数组的首地址,因此数组名本身就是一个指针,它指向第1个数组元素。其他数组元素的地址可以通过数组名加偏移量来取得。例如:

inta[20];/*定义一个长度为20的一维数组a,数组元素为整型*/

int*pa;/*定义指向整型数据的指针变量pa*/pa=a;/*为指针变量赋值,注意:数组名前不加&*/

pa=&a[0];/*本语句与上句等价*/注意:上述“pa=a;”的作用是“把a数组的首地址赋给指针变量pa”,“而不是把数组a各元素的值赋给pa”。一维数组指针的应用十分灵活。例如:如果定义

inta[20],*p=a;

既定义了一个有20个元素的一维整型数组;定义了一个整型指针变量;并将数组的首地址赋给这个指针变量。则(1)数组第i个元素的地址可以用下述方法表示:&a[i]或a+i或p+i;(2)数组第i个元素的值可以用下述方法表示:a[i]或p[i]或*(a+i)或*(p+i);

[例6-3]

假设有一个整型的a数组,共有20个元素。要求从键盘输入这20个元素,并利用下标法、数组名法和指针法等3种方法输出数组中的各元素。

方法一:下标法

main(){int

a[20],i;for(i=0;i<20;i++)scanf("%d",&a[i]);for(i=0;i<20;i++)printf("%d",&a[i]);}方法二:数组名法main(){int

a[20],i;for(i=0;i<20;i++)scanf("%d",a+i);for(i=0;i<20;i++)printf("%d",*(a+i));}方法三:指针法main(){inta[20],i,*p;p=a;for(i=0;i<20;i++)scanf("%d",p+i);pa=a;for(i=0;i<20;i++)printf("%d",*(p+i));}6.3.2指向二维数组的指针变量用指针处理一维数组时,指针变量所指对象为数组元素,即指针变量增1、减1操作就使指针后移或前移一个数组元素。但是指针处理二维数组时,指针变量所指对象是二维数组中的行,因此,无论从概念上还是使用上,二维数组的指针都要比一维数组的指针更加灵活。1.二维数组的地址

对二维数组a[3][4],

C语言将它视为有三个元素a[0]、a[1]、a[2]的一维数组(而每一个元素又是一个一维数组),

a代表整个二维数组的首地址。所以根据一维数组的表示方法,a+i代表第i个元素的地址(即第i行的首地址),a[i]和

*(a+i)表示它的第i个元素,但是这第i个元素又是一个一维数组,数组名就是这个数组的首地址,所以a[i]和

*(a+i)也代表第i个元素的地址(即第i行的首地址)。因此,对二维数组a[3][4]:(1)第i行的首地址可用下述方法表示:&a[i][0]或a+i或a[i]

或*(a+i);(2)第i行第j列的元素的地址可用下述方法表示:

&a[i][j]或(a+i)+j或a[i]+j

或*(a+i)+j

或a[0]+i*4+j等等;(3)第i行第j列的元素的值可用下述方法表示:

a[i][j]或*((a+i)+j)或*(a[i]+j)或*(*(a+i)+j);2.指向二维数组的指针变量

(1)指向数组元素的指针变量[例6-5]

用指针变量输出二维数组元素的值。程序如下:main(){int

a[3][4]={{2,4,6,8},{10,12,14,16},{18,20,22,24}};int*p;/*定义一个指向整型变量的指针变量*/for(p=a[0];p<a[0]+12;p++){if((p-a[0])%4==0)

printf("\n");printf("%4d",*p);}}程序中用a[0]至a[0]+11表示各元素的地址。(2)指向一维数组的指针变量

把二维数组a分解为一维数组a[0]、a[1]、a[2]之后,设p为指向该一维数组的指针变量,可定义为:int(*p)[4];它表示p是一个指针变量,指向包含4个元素的一维数组。若p指向第一个一维数组a[0],其值等于a、a[0]或&a[0][0],而p+i则指向一维数组a[i]。从前面的分析可得出*(p+i)+j是二维数组第i行j列的元素的地址,而*(*(p+i)+j)则是第i行j列元素的值。

[例6-6]

输出二维数组任一行任一列元素的值。main(){inta[2][3]={1,2,3,4,5,6};int(*p)[3],i,j;p=a;scanf("i=%d,j=%d",&i,&j);printf("a[%d][%d]=%d\n",i,j,*(*(p+i)+j));}程序运行结果:输入i=0,j=2回车,屏幕显示:a[0][2]=36.3.3指针数组

当一个数组的所有元素都是指针时,它就是一个指针数组,即指针数组中的每一个元素都相当于一个指针变量。一维指针数组的定义形式为:

类型名*数组名[数组长度];例如:

inta[3][4]={2,4,6,8,10,12,14,16,18,20,22,24};int*p[3]={a[0],a[1],a[2]};/*为指针数组赋初值*/指针数组中的每个元素被赋予二维数组每一行的首地址。6.4指针与字符串C语言可以用字符指针来处理字符串。例如:char

str[30],*ps=str;又例如:char

*ps="Iamastudent!“;虽然用字符数组和字符指针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,不能混为一谈,主要区别有以下几点:(1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(即字符串的首地址)。(2)赋值方式不同。(3)字符指针变量的值是可以改变的,如下列程序:main(){char

*a="Iamastudent!";a=a+7;printf("%s",a);}程序运行结果:

student!由程序可以看出,指针变量a的值可以变化,输出字符串时从变化了的a值所指向的单元开始输出各个字符,直到遇到字符串结束符‘\0’为止。而字符数组名虽然代表地址,但它的值是不能改变的。下面的写法是错的:char

s[]="Iamastudent!";s=s+7;printf("%s\n",s);6.5指针与函数指针变量既可以指向整型变量、数组、字符串,也可以指向函数。一个函数被执行时,在内存中占据一定的空间,这个空间的起始地址称为函数的入口地址,用函数名表示。可以用指针变量指向这个入口地址,并通过该指针变量调用此函数,这种指针变量称为指向函数的指针。它定义的一般形式为:数据类型

(*指针变量名)();定义了函数指针后,就可以通过它来调用所指向的函数。在调用之前,必须先将函数的入口地址赋给该指针变量。由于函数名代表函数的入口地址,因此给函数指针变量赋值时,只需给出函数名而不必给出参数。

[例6-9]

从键盘输入10个数,找出其中的最小值并输出。程序如下:#include<stdio.h>intfmin(inta[],intn){inti,min;min=a[0];

for(i=1;i<n;i++)if(min>a[i])min=a[i];return(min);}main(){int(*p)();inti,mini,a[10];for(i=0;i<10;i++)scanf("%d",&a[i]);p=fmin;/*给指针变量赋初值*/mini=(*p)(a,10);/*调用由指针变量p指向的fmin()函数,实参为a、10,得到的函数返回值赋给mini。*/

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论