一、使用内存分配应该注意的问题
检查内存是否分配成功,内存声明周期程序结束时要释放,避免导致内存泄露。使用过程中避免指针越界访问。
创建内存分配函数例子:(malloc是分配多少个字节的内存,里面是数字,且malloc分配的是堆上的内存,不是栈里面)
二、分配内存实例
void GetMemory(char*p)
{
p = (char*)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
}
malloc()分配了新的内存给p(也就是说p里面存储的或指向的是在堆里面的内存),但是你原来函数中的p是复制了str的值(str传递进去的是指针指向的地址,为NULL,不是存储str的地址。所以你可以改变的是str里面存储的地址指向内存的值)进行操作。函数执行完之后p就找不到了(因为存储p的地址是在栈上临时分配的内存),你的str并没有得到p的值,同时你把p丢了,也没有办法回收分配给p的内存。
故Test函数中的 str一直都是NULL,它并没有指向任何内存,strcpy(str, "helloworld")也不会执行成功,将使程序崩溃。
有两种办法可以改变这种情况:
第一种:传递给形参的是指针的地址。
如果改成指针变量的地址传入即二级指针则不一样。因为传递进去的是指针变量的地址,这样就可以修改指针变量地址存储的地址,即分配了内存给指针变量去指向的地址。
void GetMemory(char **p)
{
p = (char*)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str);
strcpy(str,"hello world");
printf(str);
}
第二种办法就是返回值是内存的地址,也就是返回指针变量。
这种办法在链表中常常用到。如下所示,返回在堆里面的分配的地址,然后将地址赋值给指针变量。
char* GetMemory(char*p)
{
p = (char*)malloc(100);
return p;
}
void Test(void)
{
char *str = NULL;
str=GetMemory(str);
strcpy(str,"hello world");
printf(str);
}
三、类似于fun1(char c);fun2(char *c);
main()
{
char a='a';
char *p=&a;
fun1(a);传递进去的是c里面存储的值'a';
fun2(p);传递进去的是c的地址;
}
1、如果我们在fun1里面改变c的值,在main里面a的值是不会改变的,依然是'a';
同理,我们在fun2里面改变指针(地址变量)c的值,不能改变在main里面p的值,依然是a的地址。
2、这是因为实参传递给形参的是值传递,就是将实参内存里面存储的值拷贝给形参,而不是将内存地址传递给形参;
同理,函数fun里面,会在栈里面给形参分配内存,而内存里面存储的就是实参拷贝的值。
3、所以,我们可以在fun2里面可以改变c存储的地址(&a)所存储的值a('a');
同理,如果我们在fun2里面,改变c原来所存储a的地址,也就是c里面存储是堆的地址(c=(char*)malloc(sizeof(char))),跟p没有关系。
在main里面p的值,依然是a的地址。
4、在函数里面分配的临时内存,在退出函数后会销毁。这时候c里面存储是堆的地址(c=(char*)malloc(sizeof(char)))也就
没有了,那这块在堆里面分配的内存也就找不到了,而堆不会销毁,只有等程序退出才会释放内存。
5、如果要改变p所存储a的地址,要传递的是p的地址给函数fun。