[摘 要]C语言的指针在使用时比较灵活,容易出错。本文从指针的概念入手结合内存空间的分配指出指针的实质及特点,并对常见问题进行汇总分析,以促进学生对指针学习的理解和运用。
[关键词]C语言指针内存单元
[中图分类号]TP312[文献标识码]A[文章编号]1007-9416(2010)03-0117-01
不掌握指针就是没有掌握C的精华,可见指针在C语言中的重要地位。指针是C语言中一个特殊的数据类型,灵活的运用指针可以写出简洁、紧凑、高效的程序。但是,指针概念比较复杂,运用比较灵活,容易出错,对它的理解和应用往往是初学者的一道难关。
1 指针变量的概念及特点
1.1 指针的概念
在计算机中,所有的数据和程序都是存放在存储器中。一般把一个字节空间称为一个内存单元,为了正确访问这些内存单元,必须为每个内存单元编上号,根据某个内存单元的编号即可准确的找到该内存单元,我们把内存单元的编号叫地址。通常是一个字节对应一个地址,根据内存单元的地址就可以转到所需的内存单元,我们把这个地址称为指针。在C语言中,可以用一个变量来存放指针,这个变量被称作指针变量。因此一个指针变量的值就是某个内存单元的地址,也称为某内存单元的指针。
1.2 指针的特点
指针具有两大特点,一是指针变量本身的值。指针变量的值就是某个内存单元的地址,通过指针变量中存放的地址,可以访问这些内存单元的内容。指针变量既然是变量,那肯定有自己存储空间的大小了。那么指针变量的大小是多少呢?指针是用来存放地址的,那么指针变量的长度当然就是其所在机器地址总线的长度了。比如在32位的x86上,指针一般来说就是32位的,也就是4个字节大小。二就是指针变量的类型。我们都知道声明指针变量的时候都需要指名其类型,比如char */int *等,那么这里的char/int之类的又有什么含义呢?可以把这些类型理解成一种”尺度”。如刚才所说,指针的值指明了可以访问的位置,那么指针的类型则限制了指针从该位置所能访问的长度。比如,int *p 说明了p这个指针变量在使用诸如*p等方式访问p中存放的地址中的数据的时候,系统会提取sizeof(int)长度的数据出来,这个数据当然就是一个int型的值了,或者在进行诸如p++这样的操作时,系统会加上sizeof(int)的长度。总之,指针其实就是一个地址加一个长度,地址限定了指针起始的位置,而长度则规定了系统按多少字节来访问内存的数据。
1.3 指针类型转换
有了以上的说明,关于指针强制类型转换的概念就好理解了。指针的强制类型转换的就是指针的类型,也就是系统使用指针的方式。比如从int*转换到char*,那么指针中的地址并没有变化,只是类型变了,比如在执行p++的时候,原来是增加4个字节(32位int),而转换之后便成了增加1个字节(char的长度)。再复杂一点,常规类型向结构体的强制类型转换也是这样的道理。
1.4 void指针和NULL指针
void数据类型是一种很重要的数据类型。void的意思就是“无值”或“无类型”。void指针一般称为“通用指针”或“泛指针”。之所以有这样的名字是因为使用void指针可以很容易地把void指针转换成其它数据类型的指针。例如在为一个指针分配内存空间时:
int *p;
p=(int *)malloc(…);??本来函数malloc的返回值是void类型,在这里通过在前面加上一个带括号的int*就把void*类型转换成了int*类型。所以不能简单的把void看成“无”的意思。
NULL指针是不指向任何一个地址的指针。这样的指针一般是允许的,当一个指针为NULL的时候,不要对它进行存取。
2 使用指针应注意问题及实例解析:
2.1 禁止使用“野”指针
野指针是不由程序员所能控制的指针。当在一个程序里面定义了一个指针而又没有给这个指针一个具体地址指向时,这个指针会随意地指向一个地址,这样的指针就是一个野指针。如果这个地址后面的内存空间没有什么重要的数据则不会造成不好的后果,但是一旦这里面存放了有用的数据,那么这些数据随时都有被野指针存取的危险,如果这样,数据就会被破坏,程序也会崩溃,所以在程序里面是一定要禁止任何野指针的存在。如:
int *p; *p=20; 这就属于危险操作。应改为int *p,a; p=&a;*p=20;
2.2 指针跑偏
如下例:
#include
void main()
{ char a[10],*p=a,i ;
for(i=0;i
scanf("%d", p+i);
for(i=0;i
printf(“%d”,*(p+i))
此程序用指针p输入10个元素后,p的指向已经指向了数组的末尾,此时不能直接输出。须在输出前加上 p=a;来纠正指针的位置。
2.3 内存泄漏
当一个指针使用完毕要立即释放掉这个指针所占用的内存空间--这有二方面的意义:(1)避免了内存空间的费;(2)防止了内存泄漏。产生内存泄漏是由于如果没有及时释放掉指针所占用的内存空间,而在下次使用这个指针时又给这个指针分配了内存空间,这样的次数一多,内存空间就慢慢被消耗掉了,所以形象地称这种现象为内存泄漏,如下面这样一个程序:
void *p;
for(;;)
p=malloc(20); /*这20个字节的内存空间是随意指定的*/
可以看到,每一次循环都会“吃掉”20个字节的内存,无数次之后,再多的内存也慢慢地“泄漏”,最后没有内存可用导致死机。因此需要及时释放内存,用free(p)释放掉不使用的内存。
2.4 越界问题
在使用指针访问数组时,要注意不要超出数组的低端和高端边界。由于在C语言中,数组使用时下超越所定义的上下界是不做检查的,比如下面的程序:
#include
void main()
{ char a[10],*p=a ;
while(1)
printf("%d", *(p++)
3 结语
指针是C语言的精华部分,只有理解并活用指针,才能理解C语言的精髓,才能利用它可编写出颇有特色的质量优良的程序,实现许多用其他高级语言难以实现的功能。同时由于指针使用灵活,导致容易出错,因此使用指针时要十分小心,并且在编程过程中不断总结指针的使用技巧,通过实践中的不断摸索才能准确无误地驾驭指针。
[参考文献]
[1] 谭浩强.C程序设计[M].北京:清华大学出版社,2008.
[2] 丁辉.深入理解C语言指针[J].内肛科技2005.6.
本文为全文原貌 未安装PDF浏览器用户请先下载安装 原版全文