您的位置:首页 > 编程语言 > C语言/C++

读朱兆祺攻破C语言之八---内存分配与内存释放

2013-12-10 23:57 246 查看
下面文章来自朱兆祺编写的《攻破c语言笔试和机试难点》的pdf,加上部分自己验证程序。在此感谢这位牛人为我们详尽讲解了C语言细节和难点问题。

1.1
malloc

1. 某32 位系统下,
C++程序,请计算 sizeof 的值 。

char str[] = “http://www.ibegroup.com/” ;

char *p = str ;

int n = 10;

请计算

sizeof (str ) = ?(1)

sizeof ( p ) = ?(2)

sizeof ( n ) = ?(3)

void Foo ( char str[100]){

}

请计算

sizeof( str ) = ?(4)

void *p = malloc( 100 );

请计算

sizeof ( p ) = ?(5)

答案是:

(1).25 (2).4 (3).4 (4).4 (5).4

不管是int *还是char *指针,指针长度都是4.有了这点sizeof(p) = 4应该就没有任何问题了。sizeof(n) = 4 , 因为整型长度为4。剩下sizeof(str)了,我们把char str[100]变下形你可能就知道了,其实char str[100]和*(str+100)是等效的,也就是说传进去的是指针,而不是数组,那么sizeof(str)
= 4就应该可以理解了。

2. 如程序清单8. 1所示,请问运行Test函数会有什么样的结果?

程序清单8.
1 malloc()的应用1

void GetMemory(char *p)

{

p = (char *)malloc(100);

}

void Test(void)

{

char *str = NULL;

GetMemory(str);

strcpy(str, "hello world");

printf(str);

}

我敢说很多人看到这里会冒出来的答案是: hello world 。实际上答案是:NULL 。是不是傻眼了。程序意图很简单,想通过GetMenory这个函数改变str的值。事实上,GetMemory( char *p )函数的形参为字符串指针,在函数内部修改形参并不能真正的改变传入实参的值,执行完 char *str = NULL; GetMemory(
str );这2条程序后的str仍然为NULL 。

3. 如程序清单8. 2所示,请问运行Test函数会有什么样的结果?

程序清单8. 2 malloc()的应用2

char *GetMemory(void)

{

char p[] = "hello world";

return p;

}

void Test(void)

{

char *str = NULL;

str = GetMemory();

printf(str);

}

这个是hello world 了吧 !这个还真不是输出hello world 。有同学就要问了,str = GetMemory(),而Getmemory()函数返回的是p , 而p[] = "hello world " ,怎么可能不是hello world ! 实际上,p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放。所以输出什么我也不知道,很可能是乱码。所以要理解变量的生存周期,否则就死翘翘了。

4. 如程序清单8. 3所示,请问运行Test函数会有什么样的结果?

程序清单8. 3 malloc()的应用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);

}

有些人到这里不敢吭声了,这个会是输出什么?答案是:hello。这个题目我不分析,结合上面2题请读者自己分析下。

5. 如程序清单8.
4所示,请问这个会是输出什么?

程序清单8. 4 malloc()的应用4

#include <stdio.h>

char *str()

{

char *p
= "abcdef";

return p;

}

int main(int argc, char *argv[])

{

printf("%s",
str());

return 0;

}

乍眼一看,在哪里见过?是的,确实似曾相识。有记忆了吧,会不会有人立马说出答案:输出乱码?

char *GetMemory(void)

{

char p[] = "hello world";

return p;

}

void Test(void)

{

char *str = NULL;

str = GetMemory();

printf(str);

}

上面这个题目的答案确实是:乱码!

但是char *p = "abcdef";和char p[] = “abcdef”是有区别的。char *p = "abcdef"这个程序的正确答案是输出:abcdef。

为什么?是的,有人会说,你不是说数组是可以退化成指针吗?但是,你要知道,数组是存储在栈中,p[] = “abcdef”实在执行这条语句时,abcdef才会赋给p[],并且栈在执行完成之后是会自动销毁;但是指针是保存在堆中,当开辟了*p这个地址的时候,abcdef就已经存储在p中,然而堆只有在程序结束之后才会销毁,所以是可以输出abcdef这个字符串。
1.2
malloc(0)

1. 把这个独立开来是因为很少这样使用,但是又会使用。如程序清单8.
5所示,程序会输出什么?

程序清单8. 5 malloc(0)

int main(int argc, char *argv[])

{

char *ptr = NULL;

if ((ptr = (char *)malloc(0)) == NULL)

{

printf("Null pointer\n");

printf("ptr = %#x\n", ptr);

}

else

{

printf("Valid pointer\n");

printf("ptr = %#x\n", ptr);

}

return 0;

}

我想很多人的第一个感知是输出:Null pointer!

但是很遗憾,是输出Valid pointer!虽然ptr所开辟的内存空间为0,但是ptr是不会等于NULL的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: