0.阅读引用
1.知识回顾
值传递与指针传递.
需要非常注意的问题就是:指针变量作为函数参数传递的时候,是否真正地利用指针传递能够改变其指向的值的特性来进行编程;
2.分析
2.1原题
void GetMemory(char *p) // p是str的一个副本
{
p = (char *)malloc(100);
}
void main()
{
char *str = NULL;
GetMemory(str); // 这里的str是指针变量,但是GetMemory中并没有利用【*p=...】来改变p指向的值,也不能这么做
strcpy(str, "hello world");
printf(str);
}
2.2 例子中仍然是值传递
这段代码,一看有个特别明显的错误,就是GetMemory(str)这句,可能有的人在存在疑问,str是指针
啊,有什么错误?但是你看GetMemory(char* p)里面的参数,两个都是char*类型,其实说的白话点,这
种使用方式仅仅是值传递。如果还是存在疑问,请看下面示例代码:
#include <iostream>
using namespace std;
void test(char* q)
{
q = "123";
}
int main(int argc, char** argv)
{
char* p = "abc";
test(p);// p是一个指针变量,这里的传递方式还是值传递,如果是指针传递,应该写成test(&p)
cout<<p<<endl;
return 0;
}
// 打印出的结果仍然是abc
2.3 问题分析
这个一个考验对指针理解的题目,上面程序在运行之后:
1.调用GetMemory(str)后,str并未产生变化,依然是NULL,只是改变的str的一个拷贝的内存的变化;
p只是str的一个副本,值传递,在函数调用之后并没有将p的内容传回,函数结果时将这块内存销毁;
2.strcpy(str, "hello world" );str的值仍然是NULL,在堆上和栈上都没有申请内存,程序运行到这将
奔溃;
3.申请内存的时候可能出错,应该在*p = (char *) malloc( num ); 后判断内存是否申请成功,应加上:
if ( *p == NULL )
{
...//进行申请内存失败处理
}
4.动态创建的内存没释放,会造成内存泄漏.
3.解题
3.1 方法一(返回在堆空间上申请的内存的地址)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* getMemory(int num)
{
char *p = (char*)malloc(num);//在堆区申请的空间,记得释放哦.....
return p;
}
int main(int argc, char ** argv)
{
char* str = getMemory(100); //返回的是堆空间,需要手动释放
strcpy(str, "hello world!");
printf("%s\n",str);
free(str); //内存释放
str = NULL; //不加这句会产生野指针哦
return 0;
}
3.2 方法二(利用指针传递来实现)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void GetMemory2(char **p, int num)
{
*p=(char*)malloc(sizeof(char)*num);
printf("*p's address is %p\n",*p);
if(*p == NULL){
printf("malloc error\n");
}
}
int main()
{
char *str = NULL;
GetMemory2(&str,100);
printf("str's address is %p\n",str);
strcpy(str,"hello world");
printf("str is %s\n",str);
free(str);
str=NULL;
return 0;
}