掌微面试的时候,经理GG先让我做了几道题目,第一道题目是关于动态内存传递的,之前在《程序员面试宝典》看到过,但当时没有弄明白就过去了,结果这次就丑大了,我悔!于是下决心把它好好弄明白。
题目是这样的:
void GetMem(char *p, int num)
{
p = (char *)malloc(sizeof(char)*num);
}
int main(int argc, char* argv[])
{
char *str = NULL;
GetMem(str, 100);
strcpy(str, "hello");
return 0;
}
让我改错,看程序有什么问题。
当时只觉得申请了内存空间,却并没有释放掉,其实还有更大的问题,经理大哥提醒了我也没明白过来,汗。还好经理大哥很有耐心,帮我一起做,感动!!
让我们来看看程序的整个过程,先是在主函数中定义了一个指针 str,指向为空,然后调用函数GetMen,把str传个了p,于是p也指向为空。函数GetMen中,编译器也为p开了一个空间,虽然它现在也指向空,但是它与str是两个值,他们在内存中都有自己的地址。接着是给p分配100字节的内存空间,现在p有所指了,但是str仍指向空。再下面就是把字符串"hello"复制到str所指向的空间去,然而str指向为空,当然要出错了。
其实到这里已经非常清楚,只要让str也指向p指向的空间就可以了,也就是把p返回给str就好了,这样改也最方便。
如下:
char * GetMem(char *p, int num)
{
p = (char *)malloc(sizeof(char)*num);
//加一些输出看看结果
cout<<*p<<endl;
cout<<p<<endl;
cout<<&p<<endl;
return p;
}
int main(int argc, char* argv[])
{
char *str = NULL;
str = GetMem(str, 100);
strcpy(str, "hello");
//加一些输出看看结果
cout<<*str<<endl;
cout<<str<<endl;
cout<<&str<<endl;
return 0;
}
让我们看看其输出结果
? *p
屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯 p
屯屯屯屯屯屯屯屯屯屯?
0x0012FF28 &p
h *str
hello str
0x0012FF7C &str
可以看到p在内存中的地址是0x0012FF28,str在内存中的地址是0x0012FF7C。str现在输出的结果也是我们所希望看到的。
另外还可以用传递 指针的指针 的方式来申请内存空间。
改成:
void GetMem(char **p, int num)
{
*p = (char *)malloc(sizeof(char)*num);
//加一些输出看看结果
cout<<*p<<endl;
cout<<p<<endl;
cout<<&p<<endl;
}
int main(int argc, char* argv[])
{
char *str = NULL;
GetMem(&str, 100);
strcpy(str, "hello");
//加一些输出看看结果
cout<<*str<<endl;
cout<<str<<endl;
cout<<&str<<endl;
return 0;
}
看一下其输出:
屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯
屯屯屯屯屯屯屯屯屯屯?
0x0012FF7C
0x0012FF28
h
hello
0x0012FF7C
可以看到,现在p中存的是str的地址,那么给*p分配空间也就是给str分配空间了。想明白了这一点,心中便豁然开朗。
百家讲坛中,曾仕强教授讲胡雪岩的故事,他说,胡雪岩看书,一定要把所看的弄明白,应为他知道,不弄明白,那就白看了。白白的花了时间和精力,却没有任何收获。我之前就是这样了。
我想,伟大的事情都是点滴积累起来的,就从点滴做起吧。