`
值得深入
  • 浏览: 15055 次
  • 性别: Icon_minigender_1
  • 来自: 纠结的后空翻
最近访客 更多访客>>
社区版块
存档分类
最新评论

指针参数是如何传递内存~

阅读更多
如果函数的参数是一个指针,不要指望用该指针去申请动态内存。示例7-4-1中,Test函数的语句GetMemory(str, 200)并没有使str获得期望的内存,str依旧是NULL,为什么?
----------------------------------------------------------------------------------------------------
void GetMemory(char *p, int num)//zbf:感觉非常隐蔽,设计错误
{
         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,它返回的始终是同一个“只读”的内存块。
程序运行如下:
vc->File->new->c++source file
#i nclude "iostream.h"
#i nclude "stdio.h"
#i nclude "string.h"
#i nclude "malloc.h"
void GetMemory(char *p,int num);
void Test(void);
void GetMemory2(char **p,int num);
void Test2(void);
char *GetMemory3(int num);
void Test3(void);
char *GetString(void);
void Test4(void);
char *GetString2(void);
void Test5(void);
void main()
{
// Test();
Test2();
Test3();
Test4();
Test5();
}
void GetMemory(char *p,int num)//设计错误,却非常隐蔽
{
p=(char*)malloc(sizeof(char)*num);
}
void Test(void)
{
char *str=NULL;
GetMemory(str,100);
strcpy(str,"hello");
cout<<str<<endl;
}
void GetMemory2(char **p,int num)
{
*p=(char*)malloc(sizeof(char)*num);
}
void Test2(void)
{
char *str=NULL;
GetMemory2(&str,100);//注意参数传递
strcpy(str,"hello");
cout<<str<<endl;
free(str);//保持与malloc的配对
}
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);//保持与malloc的配对
}
char *GetString(void)
{
char p[]="hello";
return p;//warning:return address of local variable or temporary(数组属于局部变量)
}
void Test4(void)
{
char *str=NULL;
str=GetString();
cout<<"以下内容为垃圾:  ";
cout<<str<<endl;
}
char *GetString2(void)
{
char *p="hello";
return p;
}
void Test5(void)
{
char *str=NULL;
str=GetString2();
cout<<str<<endl;
}
运行结果:
hello
hello
以下内容为垃圾:(随意的内容)
hello
本文出自 “国产0与1” 博客,请务必保留此出处http://qq164587043.blog.51cto.com/261469/48919

分享到:
评论

相关推荐

    C++指针参数传递内存详解

    C++指针参数传递内存详解 C++中的指针参数传递是一种常见的编程技术,但是许多开发者对其机理不甚了解,本文将深入剖析C++指针参数传递的内存机理,解决开发者们长期以来对函数指针参数传递的误解。 函数指针参数...

    指针参数传递内存

    用图片的和代码的方式解释指针参数传递内存

    值传递,指针传递,引用传递的区别,内含可运行代码和详细解释

    总结:在实际使用中,值传递一方面会占用内存空间,内置类型还好(int等),如果是类(class)类型,赋值可能会是很大一笔...而对于指针传递,则在涉及数组的情况下使用较多,因为指针本身会给代码增加复杂性,难维护性

    易语言传递指针参数.e

    .版本 2 .支持库 spec ........ ...q.b = “ddddd” 子程序1 (取变量地址 (q)) 调试输出 (q.a) ' 子程序1 b ...拷贝内存03_ (a, 参数, 8) ' 不能写成 拷贝内存03_ (取变量地址 (b), 参数, 8) 调试输出 (b.a, b.b) b.a = 125

    c语言指针变量作为函数参数传递

    总的来说,指针变量作为函数参数传递是C语言中一种非常重要的技术,它能够允许函数直接访问和修改函数外部的数据,扩展了函数的功能,但同时也对程序员提出了更高的要求,特别是在内存管理和错误处理方面需要更加...

    C++结构体参数与结构体指针参数区别Demo

    - 在编写函数时,可以考虑使用`const`关键字来限制指针参数的修改权限,如`void processStructPtr(const MyStruct* s)`,这可以防止无意的修改并帮助编译器进行优化。 - C++11引入了右值引用,可以用来优化大对象...

    再论指针 调用如果传递的是指针参数

    在函数`void a(int *a)`中,当我们将一个整型指针作为参数传递时,我们实际上是将该指针指向的内存地址传递给了函数。这意味着,在函数内部对`*a`的操作实际上是在改变原内存地址所指向的值。 ##### 示例: ```cpp ...

    指针传递和引用传递的区别

    在C++编程语言中,指针和引用是两种重要的概念,它们都涉及到对象的间接访问,...指针适合于动态内存管理、多级指针操作等高级特性,而引用则提供了更安全和简洁的参数传递方式,尤其适用于需要函数修改实参值的情况。

    指针进阶之数组参数和指针参数

    "指针进阶之数组参数和指针参数" 指针在编程语言中是一个非常重要的概念,了解指针的概念和使用方法是编程语言的基础。今天我们将深入探讨指针在...总结:在传递指针参数时,函数的参数可以写成一级指针或二级指针。

    指针函数作为参数传递(经典小实例)

    在C/C++编程语言中,指针函数是一种非常重要的概念,它允许我们将函数的地址作为指针进行操作,包括作为参数传递给其他函数。这种能力极大地增强了程序的灵活性和可扩展性,使得我们可以动态地执行不同的函数或者...

    C#调用CDLL带指针参数的函数

    C#中调用DLL,尤其是C或C++编译的DLL时,可能会涉及到指针参数,这是由于C#与C/C++在内存管理上的差异。本篇将详细讲解如何在C#中调用CDLL,并处理带指针参数的函数。 首先,了解C#与C/C++的区别。C#是一种托管语言...

    浅谈C语言中函数形参为指针类型的参数传递.pdf

    指针类型的参数传递有很多优点,如可以提高程序的效率、减少内存的使用等。但是,指针类型的参数传递也存在一些风险,如指针悬空、野指针等。 在函数形参中,指针类型的参数传递需要注意以下几点: 1. 指针变量的...

    指针是C语言可以用来直接访问内存地址

    其次,函数参数传递时,指针扮演了重要角色。C语言中函数参数默认按值传递,但若想让函数修改实参的值,就需要使用指针作为参数。通过传递指针,函数内部可以改变指针所指向的内存区域的内容,达到修改实参的效果。...

    易语言源码易语言指针传递对象源码.rar

    5. **指针传递对象**:在函数或方法的参数中使用指针来传递对象,可以避免复制整个对象的开销,特别是对于大型对象或者需要大量计算的场合,效率提升显著。 6. **指针的复制和比较**:易语言中的指针是可以复制的,...

    VC编程时CPU中参数的传递的方法与总结

    指针存储的是内存地址,因此,当函数接收一个指针参数时,实际上是在处理原始数据的地址。这允许函数直接操作内存,提高了效率。但需要注意,不当的指针操作可能导致悬挂指针或内存泄漏,因此在使用后应及时释放内存...

    聊聊 C 语言的内存模型与指针

    在函数参数传递时,如果希望函数能够修改指针变量本身的值,就需要使用双重指针。 通过以上介绍可知,C语言的内存模型以及指针的使用涉及到内存的分配、管理以及数据访问等多个方面。只有掌握了这些基础知识点,...

    指针的概念

    了解指针本身所占据的内存区有助于解决诸如内存泄漏等问题,并且有助于理解指针作为参数传递时的行为。 #### 六、指针的算术运算 指针支持加法和减法操作。这些运算的结果与常规的整数运算有所不同。当对指针进行...

    易语言指针传递窗口组件

    在这个特定的组件中,数据不是直接作为参数传递,而是通过指针间接传递,这使得组件可以处理更广泛的数据类型和大小。 "模拟DLL中的函数"是另一个关键点。DLL(动态链接库)是Windows操作系统中的一种共享代码库,...

Global site tag (gtag.js) - Google Analytics