对C语言中指针的学习探讨

时间:2022-09-07 05:24:57

对C语言中指针的学习探讨

摘 要: 针对指针这一C语言学习的难点和重点,介绍了变量数据类型与变量存储区大小的关系、指针数据类型与指针移动量的关系。以变量的指针、一维数组指针、行指针、结构变量的指针为例,采用对比的方法,介绍了使用指针存取的步骤和语句,并在此基础上,给出了一种对指针语法规则的理解和学习使用指针的方法。

关键词: C语言; 指针; 数据类型; 语法规则

中图分类号:TP311 文献标志码:A 文章编号:1006-8228(2012)12-39-02

Discussion on learning of pointer in C language

Xuan Zheng1, Zhao Junxuan2

(1. School of Electrical and Automation Engineering, Hefei University of Technology, Hefei, Anhui 230009, China;

2. School of Engineering, Anhui Agricultural University)

Abstract: Pointer is an emphasis and a difficulty in C language learning. First the relationships between data type of variable and the variable memory size, pointer data type and the pointer movement are introduced. Then taking pointer variable, one-dimensional array pointer, line pointer and structure pointer variable as examples, the usage of pointer access steps and statement is presented by comparative method. A method of individual understanding on pointer syntax rule and using pointer is put forward.

Key words: C language; pointer; date type; syntax rule

0 引言

C语言是功能强大的编程语言,在大一下“C语言程序设计”课程中,笔者接触到指针,当时觉得指针本事不小,但理解不了其功能和语法规则,后通过“微机原理及应用”和“单片机原理及应用”等课程的学习,特别是在掌握了CPU寻址方式后,对指针的使用有了深入的理解。

指针变量(简称指针)是一种特殊的变量,是用来存放地址的变量。当在程序中定义了

int i,*ip;char c,*cp;float f,*fp;double d,*dp;

计算机(本文程序运行环境)就会给变量i分配地址连续的2个字节单元的存储区,i存储区的起始地址为&i;给变量c分配1个字节单元的存储区,c存储区的起始地址为&c;给变量f分配4个地址连续的字节单元的存储区,f存储区的起始地址为&f;给变量d分配8个地址连续的字节单元的存储区,d存储区的起始地址为&d。显然变量的存储区大小与定义时的数据类型存储长度相一致。给指针变量ip、cp、fp、dp各分配2个连续的字节单元的存储区。实际上,指针的数据类型并不控制指针变量存储区大小,而是控制指针增1(或减1)操作移动量。如:ip++运行时会使指针ip从当前的位置朝地址增大的方向移动2个字节;cp++移动1个字节单元;fp++移动4个字节单元;dp++移动8个字节单元。放到数组中看,即指向下一个数组元素。

1 变量与变量的指针

变量是用来存放单独一个数据的。在编程中,一般根据要存放的数据类型来定义同类型的变量。例如:要存放数据+1257,安排变量x,则程序可为

例1:

int x=+1257; //定义整型变量x,并赋值

x+=5; //数据处理,通过变量名实现读写

换成变量的指针去完成,则程序可为

int x+=1257,*ip; //定义整型变量x和整型指针ip

ip=&x; //将x地址送ip,ip成为x的指针

*p+=5; //数据处理,通过变量指针实现读写[1]

前者是通过变量名对其存储区进行读写操作,我们理解与CPU直接寻址方式相对应;后者通过变量x的指针ip对其存储区进行读写,理解为间接寻址方式[2]。由于变量只存放一个数据,所以我们理解其指针的移动无实际意义。学习中遇到的另一个问题是:变量指针作为函数的参数,对实参值的影响。

例2:

int sum1(int a,int b)

{ a=abs(a); b=abs(b); return(a+b);

}

main()

{ int x=+59,y=-67,z1,z2;

z1=sum1(x,y); z2=x+y;

printf(“%d,%d”,z1,z2); //输出126,-8

}

换成用变量的指针作为函数参数,程序可为

int sum2(int *ap,int *bp)

{ *ap=abs(*ap); *bp=abs(*bp); return(*ap+*bp);

}

main()

{ int x=+59,y=-67,z1,z2;

z1=sum2(&x,&y); z2=x+y;

printf(“%d,%d”,z1,z2); //输出126,126

}

程序中将x、y的地址传给了函数sum2形参,在sum2里并没有改变x、y的存储区的位置(地址),而是改变了x、y存储区的内容。因此我们理解:只要指针作为函数形参,并在函数体里又对指针所指的存储区有赋值操作,那么将会影响实参的值[3]。

2 一维数组与一维数组的指针

一维数组用来存放一批同类型数据。例如:有10,20,30,40,50这么一批数据要存放,计划用a数组。程序可为

例3:

int a[]={10,20,30,40,50};

for (int i=0; i

a[i]=a[i]+5; //通过数组元素下标实现读写操作

若换成数组的指针去完成,程序可为:

int *arrayp; //定义同数据类型的指针变量

arrayp=&a[0]; //指针赋值

//arrayp成为数组a的指针,当前指向a数组的0号元素

for (int i=0; i

{ *arrayp=*arrayp+5; //通过指针实现读写操作

arrayp++; } //指针加1操作,指向下一个元素

由于这一批数据在内存连续存放,所以指针移动有实际意义。这里每次循环都采用*arrayp访问,但是在不同的循环次数中,arrayp指向是不同的。

3 二维数组与行指针

在C语言中,二维数组的数据按行存放[4]。若以行起始单元作为参考点,则该行中的各元素的偏离参考点的字节数=所在列号*数据类型存储长度;各元素地址=所在列号*数据类型存储长度+所在行起始单元的地址。因此,使用行指针对每一行各元素的访问,相当于对一维数组各元素的访问。

例4:

二维数组内容如图1所示,现要将各数据加上10处理,计划用arrayb存放。

程序可为:

int arrayb[3][]={{10,20,30,40,50},

{15,25,35,45,55},{16,26,36,46,56}};

int i,j;

for(i=0; i

for(j=0; j++; j

arrayb[i][j]=arrayb[i][j]+10;

换成行指针去完成,程序可为:

int i,j,(*arraybp)[5];

p=arrayb[0]; //指向起始行

for(i=0; i

for(j=0; j++; j

{ *(*arraybp+j)=*(*arraybp+j)+10;

arraybp++; //行指针移动一行

}[5]

我们理解行指针arraybp存储区里存放的是行地址,(*arraybp)取出的是该行第一个(0号)元素的地址。

4 结构变量与结构变量的指针

结构变量用来存放若干不同类型的数据。因此,结构变量的数据类型为用户定义型,即结构的各成员数据类型由用户根据实际情况定义。例如定义的结构类型如下:

struct person

{ int no;

char name[8];

int math;

int power; };

现要存放该类型数据09110,王静静,85,90,并要对后2个成员数据求平均数。程序可为:

struct person aa={09110,王静,85,90};

int avg;

avg=(aa.math+aa.power)/2;

换成结构指针去完成,程序可为:

struct person *aap;

aap=&aa; //aap成为aa的指针

avg=(aapmath+aappower)/2;

同样,我们认为aap指针移动无实际意义。结构变量和结构变量的指针作为函数参数意义不一样。上例结构变量aa(由struct person aa定义)作为实参传给形参的是一批数据09110,王静静,85,9009110;而结构变量指针aap(由struct person *aap定义)作为实参传给形参的是存放这一批数据09110,王静静,85,9009110存储区的起始地址。同变量指针作为函数参数一样,在函数里对指针所指区域有赋值操作,会影响原始数据。

5 结构数组与结构数组的指针

结构数组用来存放一批若干不同类型的数据。若有一批struct person类型数据,在程序设计中可安排该类型数组存放。

例5:

struct person arrays[]={{09110,王静静,85,90},

{09111,张一川,95,97},{09112,石金琳,78,65}};

要将各元素的math成员的值乘以80℅,程序可为:

For (int i=0;i

arrays[i].math=arrays[i]*0.8;

换成结构数组的指针完成,程序如下:

struct person *sp;

sp=&arrays[0]; //sp指向0号元素

for (int i=0; i

{ spmath=spmath*0.8;

sp++; } //移动结构指针

注意这里的sp++,其实际意义是指向下一个数组元素,而不是指向下一个结构成员。

6 结束语

采用这种对比方法学习指针,能正确建立指针概念,即定义同类型指针,要先给指针赋值确定指针指向,再通过指针对所指的存储区进行读写操作、理解拨动指针的意义等;对指针加1操作可以通过输出指针当前值来帮助理解。此外,还能加深理解数据的存放形式,即数据是借助于变量、数组、结构变量、结构数组的存储区存入内存。

参考文献:

[1] 孙力.C语言程序设计[M].中国农业出版社,2008.

[2] 宋振方等.以管理者视角突破C++指针教学难点[J].现代计算机,

2011.2:66-68

[3] 谭浩强.C程序设计题解与上机指导[M].清华大学出版社,1999.

[4] 谭浩强.C程序设计教程(第二版)[M].清华大学出版社,1999.

[5]付喜梅.浅析C语言中指针与数组[J].电脑开发与应用,2011.10:

29-32

上一篇:自制Q版卡通照 下一篇:玩转Win8应用商店