C语言数据结构系统学习之链表--1

在看这个问题之前先理解这样一个问题:为什么链表操作过程中对于结构体指针都要用malloc来开辟内存空间?
首先来看下malloc函数:
malloc使用的头文件:#include <stdlib.h>
返回值:如果分配成功,则返回指向被分配的内存的指针(此存储区的初始值不确定),否则返回空指针null,
当内存不再使用时,应使用free()函数来释放。函数返回的指针一定要适当对齐,使其可以用于任何数据对象。

再来看下什么时候用malloc和什么时候不使用malloc:
在C语言中,内存模型分为栈和堆。
这两种模型内存的分配方式是不同的,在栈中放的变量是由系统自动管理的,在函数结束后系统会自动释放,不需要认为的进行任何操作。
而在堆中存放的是用户自己管理的内存,手动分配的,malloc建立,系统不会在函数体执行结束后自动释放,需要用户手动释放函数free函数。
当你对分配的空间进行自己的管理和释放需要使用malloc,或者当你分配的空间在函数结束后还需要存在。
来看下面这个例子:

LINKLIST  *init linklist()
{
    LINKLIST *H=NULL;
    LINKLIST *S;
    int x;
    printf("请输入链表元素 或以-1结束输入")
    while(x!=-1)
    {
    s=(LINKLIST*)malloc(sizeof(LINKLIST));
    s->data=x;
    s->next=H;
    H=s;
    scanf(%d,&x);
    }
return H;
}

在定义结构体指针变量S时需要用到malloc函数
而定义结构体指针变量H时则没有用到malloc函数
S和H的区别所在是:H没有指向有效地内存地址,而S指向了有效地内存地址,因为S指向了有效地内存地址所以可以往S指向的内存地址里面写值:
S->data=x;而在后来H指向的地址就是每一个新的S指向的地址:H=S;
再举个例子

LINKLIST *S;
S->data=x;

以上这两句代码是不行的,因为S没有指向确切的地址,所以不能通过S来向它要指向的地址赋值;
但是

LINKLIST *S;
LINKLIST P;
S=&P;
S->data=x;

是可以的,因为S指向P的地址,S->data=x;等同于p.data=x;
而malloc的作用就类似以上代码的作用;但是不用再定义一个结构变量P,再让结构体指针变量S指向它的地址&P,
而是直接使用malloc函数让结构体指针变量S指向一个确切的内存地址。

LINKLIST *s;
s=(LINKLIST*)malloc(sizeof(LINKLIST));
s->data=x;

再举一个简单的例子

int * i;
*i=1;

错误

int *i = (int*)malloc(sizeof(int));
*i=1;

确是正确的再来个容易理解的例子:

void fun(int *input) 
{
    *input = 1;
}

int main()
{   
    int i;
    fun(&i);
    printf("*input = %d", i);

    while (1) {    }
    return 0;
}


 结果:i = 1;
换一种写法:

void fun(int *input) 
{
    *input = 1;
}

int main()
{   
    int *i = (int*)malloc(sizeof(int));
    fun(i);
    printf("*input = %d", *i);

    while (1) {

    }
    return 0;
}


结果也是输出 1,
也就是说指针的使用要么 取其他变量的地址来赋值,要么需要动态申请内存,否则会出现段错误。

总结一下:结构体变量与结构体指针的区别:
1.定义的局部变量的内存存放在栈空间,随着这段程序的结束,栈空间会释放;
2.结构体指针需要指向一块可用的空间,可以是栈空间也可以是malloc等申请的堆空间,才可以使用这个指针,
否则指针指向是的NULL,申请的堆空间需要手动free,否则就会内存泄漏。

在了解到malloc的使用场景后,我们再来学习下malloc的使用方法:

1、malloc()函数的头文件是stdlib.h,其函数声明如下:

     void* malloc(size_t size);

     其中参数size_t size表示动态内存分配空间的大小,以字节为单位。

    size_t 是typedef重定义的类型,重定义这样数据类型的作用就是让使用者一目了然,指示使用者这个参数表示一个长度,在       size后加上t,表示是整型相关数据类型的,以后看到xxx_t的类型,通常都是整型相关数据类型重定义。

    在这里malloc()函数的返回值是一个指针,或者说是分配后内存空间的首地址

    如果malloc()函数申请空间成功则返回一段内存空间的首地址,失败则返回NULL

2、int *p;

     p = malloc(sizeof(int));

     在这里是不能这样写的,会出现错误:从类型 'void*' 到类型‘int’的转换无效,应该改为:

       p =(int *) malloc(sizeof(int));

3、在使用malloc()函数申请的空间之前,最好用memset()函数把这段内存空间清理一下,因为用malloc()函数申请的空间仅仅保      证的是内存空间的大小,并不保证内存空间是否有数据垃圾

4、当不在使用malloc()函数申请的空间之后,应该使用如下函数释放掉这个内存空间:

     void  free(void *ptr);

     其中void *ptr是malloc()函数的返回值,也就是内存空间的首地址

     如果只知道使用,而不知道释放,则在7天*24小时运行的嵌入式产品中,很容易会出现内存泄漏,最终导致系统瘫痪
注:以上内容有涉及到整理其他博客的总结内容,侵删~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值