Status Push (SqStack &s, SElemType a)
{
//
插入元素
a
为新的栈顶元素
if (S.top – S.base>=S.stacksize) //
栈满,追加存储空间
{
S.base = (SElemType *) realloc( S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if (!S.base) exit(OVERFLOW); //
存储空间分配失败
S.top=S.base+S.stacksize;//因为用realloc时,基地址变了,所以栈顶指针也要跟着改变。但realloc会把原来的数据都搬到新的基地址上,只要新申请的空间比
//原数据大,就不会丢失。
//原数据大,就不会丢失。
S.stacksize+=STACKINCREMENT;
}
*S.top++=a;
return OK;
} //Push.
这段代码出自于《数据结构》(严蔚敏 吴伟民)第47页。函数的只要功能实现元素压栈,如果栈的空间不足够的时候利用realloc()函数进行再新分配空间,使得函数得以实现。
我们注意里边的一句代码:
S.top=S.base+S.stacksize;
在再分配空间之前,S.top指向栈的顶部。
而这句代码有是什么意思呢?S.top=S.base*S.stacksize同样是指向栈的顶部元素。这是不是多此一举呢?
我们看
realloc()
函数的一些说明。
语句
:
|
realloc (ptr, size)
|
参数
:
|
ptr
is a null pointer or a pointer previously returned by calloc or malloc or realloc function, size is an integer representing the number of byes to be allocated.
|
返回值
:
|
A pointer to the possibly moved allocated memory, if any. Returns null otherwise
|
资料来自:
http://www.picsupport.com/ccsc/REALLOC.htm
由这些资料我们可以看出,函数realloc()在使用的过程中,可能改变prt的值。如果要开辟的内存在原来的空间上不能够实现的时候,函数将在另外的地方开辟新的空间,复制数据,把原来的内存空间释放(free())返回新的内存地址。问题就是在这里了,回到我们原来的程序,如果在追加空间的时候改变了指针S.base的值,那么必须保证S.top也作响应的改变。
语句S.top=S.base+S.stacksize;保证了整个程序的安全性。
这里不能用malloc函数追加数组空间。因为malloc函数是这样的:
malloc操作系统申请空余内存的“堆”存储空间,然后把申请到的首地址返回。
若栈已满,执行到这条语句
S.base=(SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
则S.base指向新申请到的内存地址,原base地址丢失。
也就是说,你通过malloc函数申请的空间是操作系统分配的,不能通过指定起始地址来分配。
应该用realloc函数,此函数原型:
void *realloc(void *mem_address, unsigned int newsize);
语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。
注意:新的大小一定要大于原来的大小不然的话会导致数据丢失!
此函数功能:先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
为了验证realloc()函数有可能改变指针地址,我们看下面的代码。
#include<string.h>
#include<malloc.h>
main()
{
char *p,*q;
p = (char *)malloc(10);
strcpy(p,"abcdefghi/0");
printf("%d/n",p); //第一次malloc后p所指向的空间
q = p;
p = (char * )realloc(p,8521);
printf("%d
%s/n",p,p);
//可以观察realloc后p指向的地址同malloc后所指向的地址是否发生
//了变化,如果没有变化就把realloc中的第二个参数再变大一些!
free(q); //当p值得发生改变的时候,该语句将会发生错误,程序出错。因为q指向
//的空间已经被realloc()函数释放,
if(p==q)
printf("p==q");
else
printf("p!=q");
printf("/n %s",q);
printf("/n %s",p);
}
在该段程序中,如果把语句free()注释掉,我们还可以看到:语句printf("/n %s",q);和printf("/n %s",p);打印的值得还是一样的,说明realloc()的释放空间功能并没有将数据删除,只是告诉编译器没在被分配的状态下。事实上,关于free()函数,有如下的说明:
The free function causes the space pointed to by the ptr to be deallocated, that is made available for further allocation. If ptr is a null pointer, no action occurs. If the ptr does not match a pointer earlier returned by the calloc, malloc or realloc, or if the space has been deallocated by a call to free or realloc function, the behavior is undefined.
资料来自:http://www.picsupport.com/ccsc/FREE.htm
显然我们可以了解到,为什么当p的值发生改变时,使得free(q)语句出错,同时更清楚知道free()函数的本质。
-------------------------------------------------------------------------------------------------------------------
说明:本文的写作参考了一写网上资料,提供上网址:
http://www.picsupport.com/ccsc/FREE.htm
关于free(prt)函数的使用
http://www.picsupport.com/ccsc/REALLOC.htm
realloc(prt,size)的使用。
http://dev.csdn.net/article/27/27950.shtm
内存分配——realloc()函数的使用