From: http://www.51testing.com/?uid-10851-action-viewspace-itemid-73167
#include <stdlib.h> #include <stdio.h> #include <string.h> void GetMemory(char *p) { p = (char *)malloc(100); } void Test(void) { char *str = NULL; GetMemory(str); strcpy(str, "hello world!/n"); printf(str); } int main() { Test(); return 0; }
1,调用GetMemory( str )后, str并未产生变化,依然是NULL.只是改变的str的一个拷贝的内存的变化
2,strcpy( str, "hello world" );程序运行到这将产生错误。
3,malloc的时候有可能内存出错,应该在*p = (char *) malloc( num ); 后判断内存是否申请成功,应加上:
if ( *p == NULL )
{
...//进行申请内存失败处理
}
4,动态创建的内存没释放。
错误分析:
错认为 GetMemory(char *p)中的 p“就是” GetMemory(str)中的str。但p“不是”str,它只是“等于”str 。
就象:
int a = 100;
int b = a; // 现在b等于a
b = 500; // 现在能认为a = 500 ?
显然不能认为a = 500,因为b只是等于a,但不是a!
当b改变的时候,a并不会改变,b就不等于a了。
因此,虽然p已经有new的内存,但str仍然是null !
GetMemory(str); // 把str传进去,str是一个指针,而他实际上是一个int void GetMemory(char *p) // p是str的一个副本 { p=(char *)new char[100]; // p的值改变,但是str的值并没有改变。 } //而双重指针为什么就可以了呢: GetMemory(&str); //把str的地址传进去 void GetMemory(char **p) // p是str地址的一个副本 { *p = (char *)new char[100]; // p指向的值改变,也就是str的值改变。 } //修改方法1:(推荐使用这种方法) void GetMemory2(char **p)变为二级指针. void GetMemory2(char **p, int num) { *p = (char *)malloc(sizeof(char) * num); } void Test(void) { char *str = NULL; GetMemory = (&str); strcpy(str,"hello world"); printf(str); } //修改方法2: char *GetMemory() { char *p=(char *)malloc(100); return p; } void Test(void) { char *str = NULL; str = GetMemory(); strcpy(str,"hello world"); printf(str); }
第二题:
#include <stdlib.h> #include <stdio.h> #include <string.h> char* GetMemory2(void) { char p[] = "hello world!"; return p; } void Test2(void) { char *str = NULL; str = GetMemory2(); printf(str); } int main() { Test2(); return 0; }
答案很简单,1 运行过程中会出现错误 2 会输出 乱码
题目看似不难,但程序员,尤其是初级的程序员在写代码时很容易犯的一个毛病。
C语言中,实参变量和形参变量之间的数据传递是单向的“值传递”方式,指针变量作函数参数也要遵循这一原则。调用函数不能改变实参指针变量的值(即指针的地址),但可以改变实参指针变量所指变量的值。
程序1就试图改变 str 的值,肯定不成功,getmemory执行完后,str还是NULL,所以在执行strcpy时,程序试图给NULL的指针赋值,会发生运行时错误。
程序2的问题在于 getmemory函数试图返回局部变量的地址。众所周知,局部变量的生命只存在于该函数体内,一旦离开该函数体,该局部变量便在内存中消失,所以str得到的只能是乱码。当然也不排除在某些特定的编译器上会输出“hello,world”字样。但严格的按照标准C来说,这种写法也是不被允许的
returning address of local variable or temporary
A function returns the address of a local variable or temporary object. Local variables and temporary objects are destroyed when a function returns, so the address returned is not valid.
Redesign the function so that it does not return the address of a local object.
The following sample generates C4172:
// C4172.cpp // compile with: /W1 /LD //为什么会出现这样的现象呢? float f = 10; const double& bar() { // try the following line instead // const float& bar() { return f; // C4172 }