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

如果函数的参数是一个指针,不要指望用该指针去申请动态内存。示例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,它返回的始终是同一个“只读”的内存块。

指针参数的传递(节选 C++/C 高质量编程 林锐)的更多相关文章

  1. C++/C高质量编程指南-笔记

    复习: C/C++高质量编程指南: [规则1-2-1]为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块. [规则1-2-2]用 #include <file ...

  2. c++高质量编程手册

    怡化主管强烈要求我读这本书.... 笔记尚未完成,持续更新呗.. 第1章 高质量软件开发之道 1.1 软件质量基本概念 1.1.1 如何理解软件的质量:功能性和非公能性 1.1.2 提高软件质量的基本 ...

  3. C++高质量编程笔记

    /* * 函数介绍: * 输入参数: * 输出参数: * 返回值 : */ void Function(float x, float y, float z) { - } if (-) { - whil ...

  4. C++ 高质量编程附录试题

    附录B :C++/C试题 本试题仅用于考查C++/C程序员的基本编程技能.内容限于C++/C常用语法,不涉及数据结构.算法以及深奥的语法.考试成绩能反映出考生的编程质量以及对C++/C的理解程度,但不 ...

  5. C++函数的重载,覆盖和隐藏(——高质量编程第14章)

      函数重载概念 只有C++才有重载的概念,C语言没有. 靠行参列表的不同来区别不同的重载函数, 若是全局函数和成员函数同名时,不算重载,因为它们的作用域不同,所以成员函数会将全局函数给隐藏(遮蔽)了 ...

  6. 【c++】指针参数是如何传递内存的

    [c++]指针参数是如何传递内存的   如果函数的参数是一个指针,不要指望用该指针去动态申请内存.如下: void GetMemory(char *p, int num) { p = (char *) ...

  7. 【转】【c++】指针参数是如何传递内存的

    参数策略 如果函数的参数是一个指针,不要指望用该指针去动态申请内存.如下: void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(c ...

  8. C++指针作为函数的参数进行传递时注意的问题

    应注意问题: 当指针作为函数的参数进行传递的时候,本质上还是进行的"值传递",也就是复制了一个新的指向该地址的指针变量. 只有在被调函数中,对指针进行引用操作,才可以达到不需要返回 ...

  9. c++指针参数是如何传递内存的

    参数策略 如果函数的参数是一个指针,不要指望用该指针去动态申请内存.如下: void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(c ...

随机推荐

  1. 浅谈js闭包

    相信很多人只知道闭包这个词但是具体是怎么回事就不太清楚了,最近在群里有很多小伙伴讨论这个问题但还是蒙眬眬的赶脚.索性就写了这篇文章来帮助大家一起理解闭包. 变量作用域 闭包其实想明白了很简单,但是在理 ...

  2. UVa10651(记忆化搜索)

    题意: 给一串-和o组成的字符串,你可以把“-oo"变成”o--",可以把“oo-”变成“--o",问最后最少有多少个o. 状态压缩 ,记忆化搜索 code: #incl ...

  3. http_load压力测试

    http_load是基于linux平台的性能测试工具,它体积非常小,仅100KB.它以并行复用的方式运行,可以测试web服务器的吞吐量与负载. 一.安装http_load A.进入/usr/local ...

  4. Nmap官网中众多文档如何查看

    打开Nmap(nmap.org)官网后,会看多个关于文档的链接,熟悉之后会发现有三类,Reference Guide,Books,Docs.通过熟悉知道Doc是文档的入口,且下面是对Doc页面的翻译, ...

  5. [Google Code Jam (Qualification Round 2014) ] B. Cookie Clicker Alpha

    Problem B. Cookie Clicker Alpha   Introduction Cookie Clicker is a Javascript game by Orteil, where ...

  6. [Codeforces Round #186 (Div. 2)] B. Ilya and Queries

    B. Ilya and Queries time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  7. 在Fedora 20下编译安装QEMU

    由于OpenStack的流行,现在越来越多的人关注QEMU,最近发行了新版本1.7,下面就说Fedora下的安装过程: 首先需要安装基本的编译软件和git sudo yum install gcc m ...

  8. 解决PopupWindow遮住输入法

    1: PopupWindow中的设置 pop.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); pop.setSoftInputMode(Win ...

  9. Thread详解

    具体可参考:Java并发编程:Thread类的使用,这里对线程状态的转换及主要函数做一下补充. 一.线程状态转换图 注意: 阻塞状态是线程阻塞在synchronized代码块时的状态,而阻塞在Lock ...

  10. SQL省市区三级表结构

    -- 表的结构 areaDROP TABLE  area;CREATE TABLE  area (   id int NOT NULL ,  areaID int NOT NULL,  area va ...