malloc与realloc在栈中的操作问题

初识malloc与realloc

malloc与realloc函数大部分人可能实在C语言中接触到,我们知道,这两个函数是动态的使用内存,那么这样的好处为

1.不需要预先分配存储空间

2.分配空间的大小可以根据程序扩大或缩小

3.有效的使用内存空间

定义:

void *malloc(size_t size)//即括号里一个参数,如果开辟整型4位数的空间,那么括号里应为(sizeof(int)*4);

void free(void *pointer);//括号的参数也是一个指针

这两个函数都在头文件stdlib.h中声明。

malloc的作用是在内存的动态存储区中分配一个长度为size的连续空间,参数为无符号整型数,返回值为一个指向它所分配的连续存储域的起始地址(即指针)

注意如果未分配成功,就会返回一个NULL指针(所以在使用时应该保证非空,加一条语句判断即可)

如果初始空间不够使用时,那么realloc就派上用场了。

我们首先看realloc的定义

void *realloc(void *p,size_t new size);

realloc只要用于修改一个原先已经分配的内存块大小,可以使一块内存扩大或缩小。

注意

参数中的*p为 你想重新为谁开辟空间的首地址,第二个参数为 原先已经有的空间加上你想增加的空间,比如,原先我开辟了4个整型的空间,我想再增加4个,此时得需要用realloc函数

即:

int *p=(int *)malloc(sizeof(int)*4);//原先分配的4个整型空间

int *q=(int *)realloc(p,sizeof(int)*(4+4));//这里用q来指向新开辟内存空间的首地址而不用p,后续说明原因,这是为了安全操作。

注意:如果realloc失败,原先内存不改变,不会释放也不会移动。

但是如果,我只分配了四个整型空间,用指针为第7个空间进行赋值操作会发生什么呢

看下面例子:

#include<stdio.h>
int main()
{
    int *p;
    p=(int *)malloc(sizeof(int)*4);
    *(p+2)=3;
    printf("%d\n",*(p+2));
    *(p+6)=7;
    printf("%d",*(p+6));
    return 0;
}

可以明白,3的结果可以出来,那你认为能出来结果7的那个结果吗?

答案是可以的。

3
7

这是因为,malloc空间创建的是一块连续的内存,当指针指向前四个位置是正常的,但是如果你这一块连续内存空间之后还有空间时,就会出现7那个结果,这是不一定会一直能出来结果的,如果这块空间之后没有剩余空间或者被存储其他数据时,就会出现危险,所以不推荐使用。

那么说一下为什么重新定义指针*q来指向新开辟的内存空间呢?

我们知道,realloc一般是用于扩大空间来使用的,当缩小空间时会发生什么情况呢

例如

#include<stdio.h>
int main()
{
    int *p,*q;
    p=(int *)malloc(sizeof(int)*5);
    *(p+4)=4;
    printf("%d\n",*(p+4));
    *(p+6)=7;
    printf("%d\n",*(p+6));
    q=(int *)realloc(p,sizeof(int)*2);
    printf("%d",*(q+4));
    return 0;
}

而它的结果为

4
7
11080968

当缩小空间时,看结果知道在第五个位置,即*(p+4)与*(q+4)结果不同。

这是因为

当p所指向的那个空间需要更改时,realloc会在合适的地方重新创建合适的空间,把malloc里的信息复制到realloc中,而malloc中第五个空间显然没有没有复制到realloc中,那是因为空间小了,复制不过来,造成数据丢失。

如果不是用q指针指向realloc函数呢,就用原先的p指针指向新的首地址,会出现什么情况

看代码:

#include<stdio.h>
int main()
{
    int *p,*q;
    p=(int *)malloc(sizeof(int)*5);
    *(p+4)=4;
    printf("%d\n",*(p+4));
    *(p+6)=7;
    printf("%d\n",*(p+6));
    p=(int *)realloc(p,sizeof(int)*2);
    printf("%d",*(p+4));
    return 0;
}

而结果是

4
7
4

多重复执行几次发现不一定是上面结果,也有可能是:

4
7
8131848

为什么会出现这个不同结果呢

这是因为

当用p指针指向新的realloc空间的首地址时,(p+4)会出现歧义,你是在操作原先malloc函数p指针还是 realloc函数的p指针,如果是第一种情况那么之前赋值为4的结果就可以出来,如果后者,就是一个空间的地址,所以,为了避免出现问题,我们重新定义一个q指针指向realloc的空间地址,是最安全的。而原先malloc的空间会释放掉。

所以,建议重新定义指针来指向realloc函数的,尤其要修改数据时,更要小心。

那么在操作栈中,有一个地方需要我们注意

下面是入栈操作的函数

我们首先要判断栈顶指针是否溢出,如果栈满就要追加空间

注意第六行****@地方

Status Push (SqStack &S, SElemType e) { 
   if (S.top - S.base >= S.stacksize) {//栈满,追加存储空间
      S.base = (ElemType *) realloc ( S.base,
                (S.stacksize + STACKINCREMENT) * sizeof (ElemType));
       if (!S.base) exit (OVERFLOW); //存储分配失败
       S.top = S.base + S.stacksize;****@
       S.stacksize += STACKINCREMENT;//更新空间大小
   }
   *S.top++ = e;放入栈中数据
    return OK;
}

如果直接用S.top++可以吗

既然更新数据了,那么我直接让top指针加加,不就又重新指向下一个空间了吗,继续入栈就行吗

答案是不可以的,并且是极度危险的

代码中是追加存储空间的操作,里面是对*base即栈底指针进行赋值,指向realloc空间的首地址,而top指针并没有复制到新的空间区域中,也没有指向,那么,对原先的malloc内存中的top++,就又不止指向了什么地方,随意更改更会不小心出现大问题。

而用S.top指针重新赋值指向S.base+S.stacksize,再进行插入数据的操作,才是最安全的。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值