C中的指针是最方便和灵活的,也是最头疼的
。在链表的建立过程中,大家一般都用指针,那么请看
下面一段程序:
struct item_t {
typenameSomeinfo;
item_t * Next; //下一个结构的指针。
}
int built (item_t * head) //以head为头建立一个链表
{
item_t *Temp;
temp=Head;
for (int i=0;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);
}
:
:
你试着想象一下结果好吗?
再有如下的例子:
voidadd_some_item (void)
{
item_t test;
test.someinfo =make_a_new_info (....);
test.Next =NULL;
add (&test);
}
在函数执行完毕之后,test的内存将被释放掉,也就是说,在
以head为头的链表中,有一个悬空的指针!!!这会造成系统
的崩溃!!!
指针的错误是举不胜举的。
再看下面一个:
;C语言里,数组名是被看作指针来使用的,
一维数组是指针,二维数组是指向指针的指针,三
维是.........
看下面的例子:
;voi;show (int * * info,int x,int y)//打印一个x*y的数组的内容
;{
;in; i,j;
;fo; (i=0;ibr>;fo; (j=0;jbr>;printf ("%d ",info[i][j]);
;}
;printf ("\n");
;}
;}
在进行如下调用之后,你的系统有崩溃的可能!
;voi;Function (void)
;{
;in; as [10][10];
; :
; :
;sho;(as,10,10);
; :
; :
--
再见!
相逢在下一个路口!
来源:饮水思源站
视频教程列表
文章教程搜索
C语言程序设计推荐教程
C语言程序设计热门教程
|