目录
1.笔试题分析
1.1 题1
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();
return 0;
}
大家可以尝试寻找出其中的错误。
我们首先可以看程序运行的结果。
并没有打印出字符串。
分析:
1. 形参p 只是 实参str 的一份临时拷贝,对于形参的修改,不会影响到实参。所以str 实际上还是空指针。
2. strcpy,printf 对空指针 ptr操作,这都是有问题的。
3.使用malloc开辟动态内存空间后,未判断是否开辟成功
4.没有释放开辟的动态内存空间。
char* GetMemory(char** p)
{
char* p1 = NULL;
p1= (char*)malloc(100);
if (p1 != NULL)
{
*p = p1;
}
else
{
perror("malloc");
}
}
void test(void)
{
char* str = NULL;
GetMemory(&str);
strcpy(str, "hello world");
printf(str);
}
int main()
{
test();
return 0;
}
1.2 题2
char* GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();
printf(str);
}
int main()
{
test();
return 0;
}
并没有按照预期打印“hello world”
char p[] = " hello world" 它的生命周期只在它的作用域,出了GetMemory函数后,就被销毁。此时返回的指针 p 实质上是一个野指针,它指向的内容空间已经随着函数的结束,返回给操作系统,此时内容是未知。所以我们会看到屏幕打印的是随机的。
1.3 题3
void GetMemory(char**p,int num)
{
*p = (char*)malloc(num);
}
void Test(void)
{
char* str = NULL;
GetMemory(&str,100);
strcpy(str, "hello");
printf(str);
}
int main()
{
test();
return 0;
}
有问题吗?没有判断内存是否开辟成功,小瑕疵。
其次,malloc函数申请空间后,没有释放。
1.4 题4
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 置空,此时指针指向的内存空间已经返回给操作系统了,此时指针str 为野指针,后续的操作都是不合理的。
其次,他在开辟动态内存空间时,也没有判断是否开辟成功。
2. 优化通讯录
http://t.csdn.cn/yU5Lq
这是我的关于静态版本的通讯录的博客。在这篇博客中,我们选择直接创造可以保存1000个联系信息的数组。这种做法第一浪费资源,第二超出1000时,我们就无法使用。我们可以用动态内存开辟的方式,实现一个动态的通讯录程序。
2.1 通讯录成员
typedef struct contact
{
int sz;
peoinfo*data ;
int capacity;
}contact;
相对于静态版本,我们的通讯录结构体成员,多了一个capacity (容量),便于和sz 比较及时扩容,同时采取地址的方式(peoinfo * data)创造数组,可以实现动态化管理内存
2.2 初始化函数
#define capMAX 3
void Init_Contact(contact* pc)
{
pc->sz = 0;
pc->capacity = capMAX;
pc->data = (peoinfo*)malloc(pc->capacity * sizeof(peoinfo));
if (pc->data == NULL)
{
perror("Init_Contact:malloc:");
}
}
初始容量定位3 ,使用malloc函数开辟。同时判断是成功开辟。
2.3 扩容函数
void cheak_capacity(contact* pc)
{
if (pc->sz == pc->capacity)
{
pc->data = (peoinfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(peoinfo));
if (pc->data == NULL)
{
perror("check_capacity:realloc:");
return;
}
pc->capacity += 2;
}
printf("增容成功!");
}
realloc函数扩容。在增加联系人时,需要考虑到扩容问题,所以在增加联系人信息时,先调用一次扩容函数
2.4 销毁函数
我们使用malloc函数和realloc函数后,需要主动释放。我们选择在退出通讯录时,调用销毁函数,释放申请的动态内存空间。
void destroy_contact(contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->capacity = 0;
}
其他的功能实现和静态版本相同,不做更改。
源码分享:Contact2.0 · 斯文/mytest - 码云 - 开源中国 (gitee.com)
谢谢观看。