目录
第一题:
//问:下面test函数会输出什么
#Include<stdio.h>
#include<stdlib.h>
void GetMemory(char*p)
{
p=(char*)malloc(100);
}
void test(void)
{
char*str=NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
}
int main()
{
test();
}
第一题分析题目程序会崩溃:
1. GetMemory传参数时是用的传值,我们都知道传值是不会改变函数内部的值的。
这就导致了在外部用malloc开辟的空间返回的指向地址的指针无法改变test函数里的str指针。
2.既然不会改变str指针,那str还是NULL,那么在进行strcpy函数拷贝时,会出现*NULL,
我们都知道NULL未知的大小位置,所以对NULL解引用是非法操作,所以程序会崩溃。
3.另外一个错误也算是老生常谈的了,用了动态内存函数申请空间没有用free函数释放空间
还要记得将指针置空。
我们既然都知道了错误原因,那么改掉错误也就十分容易了。
改正1:(传地址调用)
//问:下面test函数会输出什么
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void GetMemory(char**p)//用二级指针去接收一级指针的地址
{
*p=(char*)malloc(100);//*p表示的是一级指针的地址(也就是str的地址),将申请好的内存后,
// 返回赋值给str,从而使外部的str的值指向了开辟好的首地址。
}
void test(void)
{
char*str=NULL;
GetMemory(&str);//传地址就没问题
strcpy(str,"hello world");//此时str不再是NULL了,而是新申请的首元素地址
printf(str);//打印出hello world
free(str);
str=NULL;//说烂了,不说了,简称一套带走,嘻嘻!!
}
int main()
{
test();
}
改正2:(返回值接收)
//问:下面test函数会输出什么
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char* GetMemory(char*p)
{
return p = (char*)malloc(100);
}
void test(void)
{
char*str = NULL;
str = GetMemory(str);//返回值接收
strcpy(str, "hello world");
printf(str);
free(str);
str = NULL;
}
int main()
{
test();
}
注意:上面的解法中虽然p是局部变量,在栈区上开辟,出了函数,p指针销毁,但动态内存函数申请的空间在堆区,出了函数不会被销毁,且指针p在销毁是已将开辟好的地址传给了str,所以可行。
第二题:
#include<stdio.h>
#include<stdlib.h>
char* GetMemory(void)
{
char p[]="hello world";
return 0;
}
void Test(void)
{
char* str=NULL;
str=GetMemory();
printf(str);
}
int main()
{
Test();
return 0;
}
原因分析:
1.由题目可知,p数组是在代码块之内创建的局部变量,是在栈区上的,p数组出了此函数
就会被销毁,返回不出任何东西,换言之就是str 接了个寂寞(手动狗头)。
2.虽然str还是指向数组首元素地址,但是那块地址已经不存在了。所以会报错。
如何改正呢?
最简单的方法就是将数组和指针在同一个函数中。
for example:
#include<stdio.h>
#include<stdlib.h>
void Test(void)
{
char p[]="hello world";
char* str=NULL;
str=p;//数组名就是首元素地址str指向h
printf(str);
}
int main()
{
Test();
return 0;
}
这样是不是非常的easy
还有几个和上面那个类似的题
for example:
#include<stdlio.h>
int * test()
{
int a=10;
return &a;//返回a的地址
}
int main()
{
int *pp =test();
*pp=20;//将a赋值,成功?
return 0;
}
显然会报错,原因基本和上题类似
经过这两题我们应该明白了,最主要的原因就在于该值创建在栈区,且返回栈区上创建的值。
在这过程其实我们也明白了,栈区的值不能被返回。改进方法之一是让这个值不是局部变量,
变成全局变量,或者是静态变量(其实就是在静态区或者堆区上创建)就可以了。
这里只讲个最简单的方法(因为咱这里是讲动态内存的题,不能在继续水下去了)
直接在变量前加上static
#include<stdlio.h>
int *test()
{
static int a=10;
return &a;//返回a的地址
}
int main()
{
int *pp= test();
*pp=20;//将a赋值,成功?
return 0;
}
至于static的用法有小伙伴不知第道的可以私信我,或者后期出一期讲解
第三题:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void Test(void)
{
char*str=(char*)malloc(100);
strcpy(str,"hello");
free(str);
if(str!=NULL)
{
strcpy(str,"world");
printf(str);
}
}
int main()
{
Test();
return 0;
}
这题主要原因:在于free函数提前释放所申请的空间,但是此时str还是指向原地址,导致strcpy进行对str的拷贝,出现了非法访问(相当于访问了一块不属于你的空间)。
解决方法:
1.可以是释放的同时将str指针置NULL,这样判断就不会成立也就不会出现后续非法访问。
2. 也可以是在使用完后释放再置空
第一种:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void Test(void)
{
char*str=(char*)malloc(100);
strcpy(str,"hello");
free(str);
str=NULL;
if(str!=NULL)
{
strcpy(str,"world");
printf(str);
}
}
int main()
{
Test();
return 0;
}
第二种:就是将free(str)和str放到printf之后。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void Test(void)
{
char*str=(char*)malloc(100);
strcpy(str,"hello");
if(str!=NULL)
{
strcpy(str,"world");
printf(str);
free(str);
str=NULL;
}
}
int main()
{
Test();
return 0;
}
但仔细看题目分析一波得到前者是答案。
这篇耗时巨大,学费了的小伙伴支持一波
欢迎各位大佬指正