在看这个问题之前先理解这样一个问题:为什么链表操作过程中对于结构体指针都要用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小时运行的嵌入式产品中,很容易会出现内存泄漏,最终导致系统瘫痪
注:以上内容有涉及到整理其他博客的总结内容,侵删~