C语言程序设计中关于指针的常见问题 崔星华 (吉林建筑工程学院,吉林 长春130021) 摘 要:本文结合作者的教学实践经验,针对学生在学习C语言指针时遇到的问题进行总结 和归纳。便于为以后的教学提供参考。 关键词:C语言;指针;变量;地址 中图分类号:TP312 文献标识码:A 文章编号:1008-7508( 2009)06-0124-02 在C语言程序设计中,指针是广泛使用的一种数据类型。运用指针编程是C语言最主要 的风格之一。利用指针变量可以表示各种数据结构;能方便地使用数组和字符串,并能象汇 编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环, 能否正确理解和使用指针是我们是否掌握C语言 的一个标志。但是由于指针太过灵活,一旦使用不当,不仅错误难查,而且会出现意想不到 的错误。因此,要编出正确而高效的程序,必须正确地理解和使用指针。 针对初学者对C语言指针的理解不够透彻,作者根据在C语言教学和使用方面的经验,在 本文中对一般教科书中讲解不够清楚或不够准确的几个问题作一详细阐述。 一、指针变量的初始化问题 指针变量同普通变量一样,使用之前不仅要定义说明,而且必须进行初始化,指针的 初始值必须是一个地址,决不允许赋予任何其他数据, 通常是一个数据的地址或地址 变量或空指针。 1、指针变量未被初始化 指针变量未被初始化,指针变量就不会被分配存储空间。在程序中如果使用了未被分配 空间的指针,就会出现难以查找的错误。 如在程序 main() {int x, p; x= 100; *p= x; printf(“*p=%d\n”,p); } 中,指针变量p因没有初始化,在执行语句*p= x;之前p的内容是未知的,当程序将100赋给 一个没有确定指向内存的指针变量p,而使得数据100被存入一个未知的单元。这个程序虽然 很小,所占的内存小,问题不明显,但实质上它却隐含着一个致命的错误。这是因为随着程 序的增大,很有可能访问到致命的地址单元,将会导致计算机系统工作区域内有用数据的破 坏,引起数据段操作系统的损毁,造成机器运行失常,甚至 “死机”。 解决方法是指针必须初始化后,才能使用。 本例中 p=&x; 程序便可正常运行。
2、指针初始值可赋值为空值 指针变量值为0的指针称为零指针(空指针)。其表示形式为int *p=0;表示p指向地 址为0的单元,系统保证该单元不作其他应用,表示指针变量值没有意义。可以写成: #define NULL (void *)0 int *p=NULL; 定义零指针主要用于避免指针变量的非法引用和在程序中比较指针变量是否为空两个方 面。因此,不能把一个空指针用于除此之外的其他比较。若某些系统允许第0号内存既可以 被写入也可以被读出,这时错用空指针可能会改写操作系统的一部分内容,从而使系统彻底 崩溃;若系统只允许读0号内存,这时空指针指向一个有用的字符串;若系统对0号单元实行 写保护,则对空指针的操作将失败。.因此,使用空指针时要特别小心。 二、指针变量赋值问题 1、指针赋值带来的内存丢失 在C语言中指针之间是可以相互赋值的,但是使用不当可能会造成部分内存的“丢失” ,即这部分内存空间不能再被该任何程序访问。如: main() {float *a, *b; a=(float)malloc( sizeof( float)); b=(float)malloc( sizeof( float)); *a= 227. 5; *b= 163. 9; a= b; printf(“%f,%f,*a, *b); } 上例中将指针变量b赋给了指针变量a,使a与b都指向分配给b的内存空间,而原先分配 给a的内存空间未释放,不能再被其它任何程序访问,该内存空间成了“无效内存块”,内 存空间“丢失”了,而a后来指向的内存单元又直接或间接地被反复调用,内存愈来愈紧张 ,最终“死机”。 解决方法:一个指针变量赋给另一个指针变量前,应先用free( )释放所占有的内存空 间,使这部分空间可以由系统重新支配,即应在赋值语句前执行:free (a)。 2、指针变量赋值错误 C语言规定,一个指针变量只能指向同类型的变量,不能时而指向一个整型变量,时而 指向一个字符型变量。当然,如果程序中确实需要进行不同类型的 指针变量进行赋值时, 则需要进行强制类型转换。 3、混淆指针变量和它所指向的数据而导致程序错误 如在程序 main() {int x, *p; x= 10; p= x; printf(“%d”,*p); } 中,语句p= x把数据10而不是10所对应的单元地址赋给指针变量p,因而printf()调用 语句无法在屏幕上显示x的值。 三、指针用于数组时应注意的问题 1、混淆数组名与指针变量的区别 main() {int i, a[ 8]; for( i= 0; i< 8; i++) scanf(“%d”,a++); } 分析:C语言中约定,指针变量是一个变量,地址为其值;数组名是一个常量指针,在 系统为数组分配存储单元时确定,其值是该数组首元素的地址。因此.数组名不能自增自减 ,也不能在赋值语句中作左值.例程中企图通过对a的改变使指针下移,指向欲输入数据的数 组元素。它的错误在于不了解数组名代表的是数组首地址,是一个地址常量,而地址常量的 值是不能改变的。 2、指针越界错误 由于对内存中数据放置的错误假定,导致指针超出数据对象所占内存空间的大小。 例:main() {int a[5], b[5] ; int *p, i ; p=a; for (i=0; i<10:i++) *p++=i;} 分析:该程序想通过指针变量p的自加运算来完成用0~9初始化数组a和b,但这是建立 在数组a和b相邻存放的基础上的,事实上这种情况并不一定成立。 3、混淆数组与指针的区别 例:main() {char *p=“beijing”; p[0]= ‘B’;} 分析:程序没有正确区分数组和指针。在C语言中,当把字符串常量赋予指针时,该字 符串常量就存储在静态存储区中。此时数据不能用指针修改,应用数组的方式进行修改。 参考文献: [1]王敬华等. C语言程序设计教程[M]. 北京:清华大学出版社,2006.264-380. [2]谭浩强. C语言程序设计[M]. 北京:清华大学出版社,1995,157-212. [3]邓鹰. 析C语言指针过程中的常见错误[J]. 青海师专学报(自然科学) 2002, (5):106-107. [4]吴斌. C语言指针的教学[J]. 安徽职业技术学院学报, 2004,(9):67-69.
收稿日期:2009-07-11 作者简介: 崔星华(1981—),吉林长春人,吉林建筑工程学院计算机系教师,吉林大学计算机学院20 06级研究生。
|