请问:一道笔试题
程序1:
char *GetMemory()
{
char p[]="hello world";
return p;
}
void Test(void)
{
char *str=NULL;
str=GetMemory();
printf(str);
}
程序2:
void GetMemory(char* p)
{
p=(char*)malloc(100);
}
void Test(void)
{
char *str=NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
}
请问这两个程序的输出结果有什么不同?
问题点数:10、回复次数:37Top
1 楼dx30611(想要clean code)回复于 2005-12-18 19:14:08 得分 0
当然不一样
第一个地址是"hello world"字符串的首地址
第二个是堆内存中分配的地址Top
2 楼steedhorse(晨星)回复于 2005-12-18 19:19:07 得分 0
第二个不好吧,C语言参数都是值传递,函数内部对参数的改变不影响外部的实参。Top
3 楼dte99(善善恶恶)回复于 2005-12-18 19:37:11 得分 0
第一个程序是错误的,getmemory函数中的"Hello world"字符串是局部变量,调用完之后即被释放,因此输出的是一段随机数据,不是"HEllo world";
第二个程序则可以,因为malloc分配的内存如果不free掉的话,是不会被释放的,因此可以正常输出"Hello world",但是因为第二个程序中没有free,所以有内存泄漏的问题。
Top
4 楼dte99(善善恶恶)回复于 2005-12-18 19:41:33 得分 0
因此虽然理论上可以正常输出,但是实际上会因为内存泄漏问题导致strcpy程序异常而程序异常退出。Top
5 楼zhangxiaoyou(弱水三千)回复于 2005-12-18 20:58:23 得分 0
!新手报到了啊 .Top
6 楼ak_2005(★★★★★)回复于 2005-12-18 21:01:03 得分 0
同意 dte99(善善恶恶)
char *str=NULL;//要报NULL pointer assignment
改为:
char *str;//就不会了Top
7 楼goodsun2()回复于 2005-12-19 01:20:57 得分 0
为什么:
char *str=NULL;//要报NULL pointer assignment
改为:
char *str;//就不会了?Top
8 楼afei_xyd(阿飞)回复于 2005-12-19 10:03:09 得分 0
第一个程序输出结果可能是乱码,因为GetMemory()返回的是指向栈内存得指针,该指针得地址不是NULL,但是内容已经被删除。
第二个程序将会崩溃,因为GetMemory()并不能传递动态分内存,Test()中str 一直是NULL,
strcpy(str,"hello world");将会使程序崩溃Top
9 楼Z_X_H(李逍遥)回复于 2005-12-19 11:34:33 得分 0
第一个程序返回一个局部变量的地址是无定义的,编译器会给出一个警告,虽然程序可正常运行,但输出内容不确定.
第二个程序不能正常运行,因为strcpy(str,"hello world");中str为NULL.虽然调用了GetMemory,但是参数还是按值传递,程序会生成一个指针的拷贝,并不会改变原来指针的值.可以用指针的引用或指针的指针代替,如void GetMemory(char*& p)或void GetMemory(char** p);Top
10 楼yan_1103(超越自我)回复于 2005-12-19 14:27:12 得分 0
是不是金智的笔试啊?Top
11 楼Acoolice()回复于 2005-12-19 16:36:20 得分 0
第一个输出是乱码;
第二个不能正常的运行!!Top
12 楼goodsun2()回复于 2005-12-20 00:39:42 得分 0
char *str=NULL;
和char *str;有什么不同?Top
13 楼langzi520(虽左但右)回复于 2005-12-20 16:44:36 得分 0
不晓得那位是标准答案啊!Top
14 楼mccxj(老鼠不逛街)回复于 2005-12-20 16:58:46 得分 10
程序1:
char *GetMemory()
{
char p[]="hello world";
return p;
}
void Test(void)
{
char *str=NULL;
str=GetMemory();
printf(str);
}
GetMomory()返回临时变量的地址..调用完了之后内容被清除,所以str只能得到一个
未知内容..乱码!
程序2:
void GetMemory(char* p)
{
p=(char*)malloc(100);
}
void Test(void)
{
char *str=NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
}
程序崩溃..因为只是在栈里边分配空间..GetMomory之后空间已经被回收..所以strcpy不能成功..
请问这两个程序的输出结果有什么不同?
这两个题目出自林锐的c/c++高质量编程一书,可以上网查找..Top
15 楼zjfeng1984(海诺)回复于 2005-12-20 19:14:07 得分 0
新手报道Top
16 楼zjfeng1984(海诺)回复于 2005-12-20 19:24:02 得分 0
笔试题考的太细致了,看来我又的好好的记些东西了 哎!!学海无崖Top
17 楼snailbreak(悄悄的来,正如我悄悄的走)回复于 2005-12-20 20:19:10 得分 0
第一题大家讲的都很好,
我讲讲对第二题的看法:
void GetMemory(char* p)
{
p=(char*)malloc(100);
}
void Test(void)
{
char *str=NULL;
GetMemory(str);//调用GetMemory函数是用str初始化形参p,p改变了,申请的空间
//的首地址也赋给了p,但是没有返回个str
strcpy(str,"hello world");//所以到这一步str仍然我NULL,执行strcpy就会出现异常,
//而且申请的空间也有泄露问题
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);
}
象这样的问题在C++中用引用可以避免。
Top
18 楼kundy(在旅途)回复于 2005-12-20 23:11:16 得分 0
snailbreak(南师杀猪的) ,补充一下:
void Test(void)
{
char *str = NULL;
str = GetMemory(str);
strcpy(str,"hello world");
printf(str);
free(str) /*这里应该加上,否则内存泄漏*/
}
说明:当调用GetMemory()函数时,str变量的值通过参数传值的方式赋给GetMemory()的局部参数p。在函数GetMemory()中调用malloc()函数在系统堆中返回一块内存,内存的首地址赋给了指变量针p。GemMemory()返回时将p所赋的地址赋给了Test()中的变量str,从而str指向了堆中的那块内存。在使用完后应该释放,否则有内存泄漏。
Top
19 楼yclr(雪阳)回复于 2005-12-21 13:50:00 得分 0
呵呵,大家都分析的好细呀
Top
20 楼cdo(Everything has a favourable turn)回复于 2005-12-21 14:32:58 得分 0
这些可以看看林锐的《高质量C++编程》Top
21 楼bm1408(向va_list学习~不用VC好多年~)回复于 2005-12-21 15:01:22 得分 0
高质量的C++编程上说的还可以吧(:Top
22 楼wcg_jishuo()回复于 2005-12-24 21:12:38 得分 0
是不是把c语言真真理解要 把汇编学好?,软件设计师 习题中那个汇编是什么汇编语言/?
大家 介绍几本好的汇编的书?Top
23 楼rockhard(不签名)回复于 2005-12-24 21:38:05 得分 0
第一题有可能输出"hello word"尽管这个程序是错误的,
char *GetMemory()
{
char p[]="hello world";
return p;
}
此处的 p是在栈中分配的局部变量,函数返回后这块内存会被回收。
(华为的笔试题目里面有这道题)
第二个根本就是错误的。
char *str=NULL;
GetMemory(str);
strcpy(str,"hello world"); //此处的str值仍然是NULL,你可以在调试器下看看
因此程序一运行就会报错,非法访问。
要弄清楚值传递与引用传递的差别
Top
24 楼hanxuaiztt(依旧飘流)回复于 2005-12-24 22:26:15 得分 0
我只知道用了malloc,后面就应该用一个free。其他的我真的不只到还有什么了
哎,没个老师指导我就是菜啊!Top
25 楼yk9394(空)回复于 2005-12-24 22:47:49 得分 0
华为面试题中有这样一题Top
26 楼nagon()回复于 2005-12-24 23:05:12 得分 0
两个都有问题啊。区别是第一个可以跑,第二个不能跑。
这种和编译器平台关系不大的东东用VC跑跑看嘛。Top
27 楼chengzanmiao(高薪為共產當多納稅)回复于 2005-12-25 11:19:40 得分 0
GetMemory()
这样用根本得不到函数内分配的内存,返回一个不确定的地址.Top
28 楼yleiou(单刀匹马)回复于 2005-12-25 11:49:23 得分 0
解析的都很好Top
29 楼ruiding(瑞丁)回复于 2005-12-25 13:05:07 得分 0
呵呵 面试了十几个公司 至少有90%的公司都出这个题.......Top
30 楼iamcaicainiao(老菜,长征)回复于 2005-12-25 19:27:44 得分 0
以下摘自《林锐-高质量c++c编程指南》-----标准答案
指针参数是如何传递内存的?
如果函数的参数是一个指针,不要指望用该指针去申请动态内存。示例7-4-1中,Test函数的语句GetMemory(str, 200)并没有使str获得期望的内存,str依旧是NULL,为什么?
void GetMemory(char *p, int num)
{
p = (char *)malloc(sizeof(char) * num);
}
void Test(void)
{
char *str = NULL;
GetMemory(str, 100); // str 仍然为 NULL
strcpy(str, "hello"); // 运行错误
}
示例7-4-1 试图用指针参数申请动态内存
毛病出在函数GetMemory中。编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory就会泄露一块内存,因为没有用free释放内存。
如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,见示例7-4-2。
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(sizeof(char) * num);
}
void Test2(void)
{
char *str = NULL;
GetMemory2(&str, 100); // 注意参数是 &str,而不是str
strcpy(str, "hello");
cout<< str << endl;
free(str);
}
示例7-4-2用指向指针的指针申请动态内存
由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。这种方法更加简单,见示例7-4-3。
char *GetMemory3(int num)
{
char *p = (char *)malloc(sizeof(char) * num);
return p;
}
void Test3(void)
{
char *str = NULL;
str = GetMemory3(100);
strcpy(str, "hello");
cout<< str << endl;
free(str);
}
示例7-4-3 用函数返回值来传递动态内存
用函数返回值来传递动态内存这种方法虽然好用,但是常常有人把return语句用错了。这里强调不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡,见示例7-4-4。
char *GetString(void)
{
char p[] = "hello world";
return p; // 编译器将提出警告
}
void Test4(void)
{
char *str = NULL;
str = GetString(); // str 的内容是垃圾
cout<< str << endl;
}
示例7-4-4 return语句返回指向“栈内存”的指针
用调试器逐步跟踪Test4,发现执行str = GetString语句后str不再是NULL指针,但是str的内容不是“hello world”而是垃圾。
如果把示例7-4-4改写成示例7-4-5,会怎么样?
char *GetString2(void)
{
char *p = "hello world";
return p;
}
void Test5(void)
{
char *str = NULL;
str = GetString2();
cout<< str << endl;
}
示例7-4-5 return语句返回常量字符串
函数Test5运行虽然不会出错,但是函数GetString2的设计概念却是错误的。因为GetString2内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。
Top
31 楼youngdreamer2008(羊追馍)回复于 2005-12-25 22:52:28 得分 0
受益匪浅!!!Top
32 楼armman()回复于 2005-12-26 11:14:01 得分 0
各位聪明啊
小弟总感觉有点模糊Top
33 楼Mi_Bo(长弓落日)回复于 2005-12-26 12:06:43 得分 0
#include "stdio.h"
#include <stdlib.h>
#include <string.h>
void GetMemory(char** p)
{
*p=(char*)malloc(100);
}
void main(void)
{
char *str=NULL;
GetMemory(&str);
strcpy(str,"hello world");
printf(str);
free(str);
}Top
34 楼sky_1982(好好学习)回复于 2005-12-26 13:35:48 得分 0
同感: snailbreak(南师杀猪的)
Top
35 楼pinel()回复于 2005-12-26 13:58:00 得分 0
引用也可以
#include "stdio.h"
#include <stdlib.h>
#include <string.h>
void GetMemory(char* &p)
{
p=(char*)malloc(100);
}
int main(void)
{
char *str=NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
free(str);
system("PAUSE");
return 0;
}
Top
36 楼kevinlvchina(凯文)回复于 2005-12-26 19:45:45 得分 0
char *p = (char *)malloc(sizeof(char) * num);
return p;
如果这样分配的内存就在堆上了,不会随程序消亡而消亡,是这样吗?Top
37 楼benjaming1981(ben)回复于 2005-12-26 20:34:32 得分 0
程序2
传递参数时,都是传递副本
所以副本指针指向申请的空间
原指针仍为空
不仅没打印出hello world
而且 内存泄漏Top




