C 中的指针是最方便和灵活的,也是最头疼的。在链表的建立过程中,大家
一般都用指针,那么请看下面一段程序:
struct item_t { typename Someinfo ;item_t * Next ; // 下一个结构
的指针。
}
int built (item_t * head ) // 以head为头建立一个链表{ item_t * Temp
;
temp =Head;for (int i=0 ;i<ITEMNUM ;i++ ) { temp = (item_t *)
malloc(sizeof(item_t));if(temp==NULL)
return 0;temp =temp->Next;} return 1;} 短短的一段程序,想当然的
写成了这样,其中有将近四个错误一是传进来的 head 在函数里没有任何改变。
二是就算 head 在函数里被改变,可对于调用者 built(pointer )来说,在函
数调用结束之后pointer 的值并没有任何改变!!第三,让我们来看看建立过程,
先为temp分配一段空间,然后再将temp置为temp->next,我们不妨在这儿将程序
改为
temp1 =temp ;//新增加的语句temp =temp->next;然后又循环过来,又给
temp分配空间,注意!!temp1->next 的值并没有改变,程序所做的只是将temp
重新赋了一个值而已!
这样的程序只有出毛病的份了。
现将上一次的程序加上一个函数
int add (item_t * obj);功能是将obj 指向的结构放在链表的尾端,函
数体如下:
int add (item_t * obj)
{ item_t * Temp ;
if(obj==NULL )
return 0;
Temp =head;//head为一全局变量,为队列的头指针。
while (Temp->Next!=NULL ) { Temp =Temp->Next ;} Temp->Next =obj
;return 1;}
这里首先有一个问题:如果队列为空如何处理?
于是需要加入如下程序段:
if(head==NULL) { head =obj;return 0;} 可是运行这样的程序是要冒
极大的风险的,因为函数包括了以下的几个约定:
1:所有的item_t类型的元素被初始化时,他的Next指针必须被初始化为 NULL.
2:所有传递给 add(item_t *)的指针必须是不同元素的地址!而且最好是用
动态分配的。
如果这两条没有被很好的遵守的话,麻烦就来了,看如下的调用:
:for (int i=0 ;i<10;i++ ) { item_t test;test.Someinfo =make_a_new_info
(……);test.Next =NULL ;add (&test );} :你试着想象一下结果好吗?
再有如下的例子:void add_some_item(void)
{ item_t test ;test.someinfo =make_a_new_info(……);test.Next
=NULL ;add (&test );} 在函数执行完毕之后,test的内存将被释放掉,也
就是说,在以head为头的链表中,有一个悬空的指针!!!这会造成系统的崩溃!!!
足够多的指针了吗?不!指针的错误是举不胜举的。
再看下面一个:C语言里,数组名是被看作指针来使用的,一维数组是指针,
二维数组是指向指针的指针,三维是……
真的是这样的吗??
看下面的例子:
void show (int * * info,int x ,int y )//打印一个x*y 的数组的内
容{ int i ,j ;for (i=0 ;i<x ;i++ ) { for(j=0 ;j<y ;j++ ) { printf
("%d " ,info[i][j]);} printf("\n");}
在进行如下调用之后,你的系统有崩溃的可能!
void Function (void)
{ int as [10][10] ;:show(as,10,10);:} 为什么?在c 中,二维
数组虽然是定义为指向指针的指针,但是实际上被指向的指针是不存在的,只是
在执行as [n]时返回一个指针罢了,as所指的不过是存放数组内容的地址!!
如何避免指针错误*********************************************************
这是一个很大的题目,如我所说,指针的错误是多种多样的没有一个完全的
方法来避免,但因此而不用指针亦是不可取的。避免指针错误的方法,就我而言,
最有效的规则就是:管好自己的指针。包括以下几点:
1:基本保证函数分配的指针在函数结束时被释放。
(或被某些外部指针引用)
2:如要引用某些传递进来的指针,可先Copy一个备份,坚持不修改外部变
量的原则。
3:对于每个指针有个清晰的规划和说明。