局部变量作为返回值

2023-10-27

一般来说,函数是可以返回局部变量的,局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错,因为函数只是把指针赋值后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错。准确的来说,函数不能返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的)
下面以函数返回局部变量的指针举几个典型的例子来说明:

#include <stdio.h>   
char *returnStr()   
{   
    char *p="hello world!";   
    return p;   
}   
int main()   
{   
    char *str;   
    str=returnStr();   
    printf("%s\n", str);   
    return 0;   
}

这个没有任何问题,因为"hello world!"是一个字符串常量,存放在只读数据段,把该字符串常量存放的只读数据段的首地址赋值给了指针,所以return Str函数退出时,该字符串常量所在内存不会被回收,故能够通过指针顺利无误的访问。

#include <stdio.h>   
char *returnStr()   
{   
    char p[]="hello world!";   
    return p;   
}   
int main()   
{   
    char *str;   
    str=returnStr();   
    printf("%s\n", str);   
    return 0;   
}   

"hello world!"是局部变量存放在栈中。当returnStr函数退出时,栈要清空,局部变量的内存也被清空了,所以这时的函数返回的是一个已被释放的内存地址,所以有可能打印出来的是乱码。

int func()  
{  
      int a;  
      ....  
      return a;    //允许  
}                     
  
int * func()  
{  
      int a;  
      ....  
      return &a;    //无意义,不应该这样做  
}   

局部变量也分局部自动变量和局部静态变量,由于a返回的是值,因此返回一个局部变量是可以的,无论自动还是静态,
因为这时候返回的是这个局部变量的值,但不应该返回指向局部自动变量的指针,因为函数调用结束后该局部自动变量
被抛弃,这个指针指向一个不再存在的对象,是无意义的。但可以返回指向局部静态变量的指针,因为静态变量的生存
期从定义起到程序结束。

如果函数的返回值非要是一个局部变量的地址,那么该局部变量一定要申明为static类型。如下:

#include <stdio.h>   
char *returnStr()   
{   
    static char p[]="hello world!";   
    return p;   
}   
int main()   
{   
    char *str;   
     str=returnStr();   
    printf("%s\n", str);   
  
    return 0;   
}  

数组是不能作为函数的返回值的,==原因是编译器把数组名认为是局部变量(数组)的地址。返回一个数组一般用返回指向这个数组的指针代替,而且这个指针不能指向一个自动数组,因为函数结束后自动数组被抛弃,但可以返回一个指向静态局部数组的指针,因为静态存储期是从对象定义到程序结束的。==如下

int* func( void )  
{  
   static int a[10];  
   ........  
   return a;  
}   

返回指向堆内存的指针是可以的

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 申请任意多少的内存,程序员自己负责在何时用 free释放内存。动态内存的生存期由程序员自己决定,使用非常灵活

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

局部变量作为返回值 的相关文章

  • C++多态

    个人简介 作者简介 大家好 我是菀枯 支持我 点赞 收藏 留言 格言 不要在低谷沉沦自己 不要在高峰上放弃努力 前言 之前我们已经将面向对象三大特性中的封装和继承讲了 接下来剩下最后一个环节了 那就是 多态 多态概念 通俗来说 就是去做相同
  • Winform项目之学生成绩管理系统设计与实现(三)

    1 班级管理 private ClassService classService new ClassService public ListClassForm InitializeComponent this dgvListClass Row
  • std::vector简介及其使用(转)

    std vector简介及其使用 本文中的vector指的是std vector C 11标准 Vector概述 template
  • C++学习(四十一)stderr stdout

    stdout 标准输出设备 stderr 标准错误输出设备 两者默认向屏幕输出 但如果用转向标准输出到磁盘文件 则可看出两者区别 stdout输出到磁盘文件 stderr在屏幕 在默认情况下 stdout是行缓冲的 他的输出会放在一个buf
  • C++类的拷贝(复制)构造函数深入理解

    目录 一 拷贝构造函数的基本了解和使用 二 拷贝构造函数的一些注意事项 三 拷贝构造函数的调用时机 使用一个对象 直接构造 显式构造 或 初始化 隐式构造 另一个同类对象 关于拷贝构造函数与赋值函数的区别与联系 作为函数的形式参数时 作为函
  • C++ STL模板库用法查询及一些常见面试题(自用)

    C STL模板库 文章目录 C STL模板库 用法查询 Array 1 使用 2 创建 3 成员函数 Vector 1 使用 2 创建 3 成员函数 deque 1 使用 2 创建 3 成员函数 list 1 使用 2 创建 3 成员函数
  • C++ string类的实现

    个人简介 作者简介 大家好 我是菀枯 支持我 点赞 收藏 留言 格言 不要在低谷沉沦自己 不要在高峰上放弃努力 前言 在C语言中 没有专门用来表示字符串的类型 C语言的字符串是一系列以 0 为结尾的字符的集合 虽然C语言为这样的字符串提供了
  • ##顺序表 编码##

    ifndef LIST H define LIST H class List public List int size List 析构函数 void ClearList 清空线性表 bool ListEmpty 判断线性表是否为空 int
  • 第二章排错的工具:调试器Windbg(下)

    感谢博主 http book 51cto com art 200711 59874 htm 2 2 读懂机器的语言 汇编 CPU执行指令的最小单元 2 2 1 需要用汇编来排错的常见情况 汇编是CPU执行指令的最小单元 下面一些情况下 汇编
  • 内联函数及其注意事项

    default argument 是编译器记住了default argument 但是运行时还是要两个参数的 编译器看到了原型声明 可以有default argument值 所以编译器替你补上了 建议 不要使用default argumen
  • c#泛型

    参考博文 http www cnblogs com 1175429393wljblog p 5519701 html 泛型类型参数 其是一个占位符 不是一个真正的类型 而更像是一个类型的蓝图 当我们在声明 实例化该类型的变量时 则把T改为指
  • C++学习(四三五)android获取so安装路径

    ClassLoader loader getClassLoader try Method library ClassLoader class getDeclaredMethod findLibrary String class String
  • 关于C++对象模型(下)

    下篇主要讨论调用成员函数 访问成员变量的开销 及其特殊成员函数 数组 异常处理的讨论 这篇文章中出现的对象定义都出现在上篇中 全文在这里下载 文章内容转自 http tb blog csdn net TrackBack aspx PostI
  • C++学习记录6--srand(time(NULL)产生随机数

    time 函数 返回从1970 1 1 00 00 00到调用time 函数时所经过的时间 以秒为单位 所以是个整数 time NULL 或time 0 表示在内存中不存储返回的数值 头文件 include
  • C++的指针与引用可能并不难,只是你没理解

    目录 复合类型 引用 引用即别名 引用的定义 引用的两种例外情况 指针 获取对象的地址 指针值 利用指针访问对象 某些符号有多重含义 空指针 建议 初始化所有指针 赋值和指针 其他指针操作 void 指针 理解复合类型的声明 定义多个变量
  • [C++] IO流,文件输入输出,string流,类型转换运算符

    文章目录 类型转换运算符 循环输入原理 文件输入输出 简介 文件模式 二进制读写与文本文件读写 string 流 istringstream 使用 ostringstream 使用 类型转换运算符 循环输入原理 循环输入 有些oj题会要求我
  • C++给变量起别名

    以下代码展示给变量a取一个别名b 两者指向同一个内存空间位置 改变b a也会相应改变 include
  • C++征途 --- List链表容器

    第一部分 基础概念 上面这个模型的是一个单向链表 优点 1 链表增加和删除节点的时候不需要进行vector数组那样的增完后进行后移 也不需要删完后前移 当它增加一个节点的时候 只需要将它插入的位置的上一个节点的指针域中的指针指向增加的节点
  • C++中的friend详细解析

    https blog csdn net u012861978 article details 52095607
  • C#学习 - 事件 续

    事件声明 完整声明 using System namespace ConsoleApp1 internal class Program static void Main string args Customer customer new C

随机推荐

  • C++的特性(封装、继承、多态、抽象)的详解

    封装 封装目的 模块化 信息隐藏 封装 隐藏对象的属性和实现细节 仅对外公开接口和对象进行交互 将数据和操作数据的方法进行有机结合 是通过特性和行为的组合来创建新数据类型让接口与具体实现相隔离 C 中是通过类来实现的 为了尽量避免某个模块的
  • MIPI I3C简介

    前面的文章介绍过MIPI联盟发布的MIPI CSI DSI D PHY等接口 这一篇文章来简单聊一聊I3C 同样由MIPI联盟制定 主要用于替代传统的USRT I2C和SPI 并向下兼容I2C 由于已经有网友写过相关的文章 并且写的很不错
  • signature=462fd3702561f02c1dc8858a887d01f8,baly-20201118

    0001747079 20 000139 txt 20201119 0001747079 20 000139 hdr sgml 20201119 20201119073031 ACCESSION NUMBER 0001747079 20 0
  • EF(Entity Framework)通用DBHelper通用类,增删改查以及列表

    其中 通用类名 DBhelper 实体类 UserInfo 1 新增 2 DBHelper
  • wedo巡线机器人编程教程_这是一个机器人和编程的时代

    图中在草地上自在奔跑的机器人是波士顿动力公司 BostonDynamics 开发的类人双足机器人Atlas 由麻省理工 MIT 电子工程与计算机科学系的教授马克 雷波特在1992年创立 一直致力于将机器人变成自然界的一个新物种 经过20多年
  • Springboot集成knife4j实现风格化API文档

    Springboot集成knife4j实现风格化API文档 POM引入插件
  • GoLang之使用uber-go/dig进行依赖注入

    文章目录 GoLang之使用uber go dig斤进行依赖注入 1 依赖输注入介绍 2 main函数反面例子 3 下载DI依赖 4 main函数使用DI优化 5 注意点 GoLang之使用uber go dig斤进行依赖注入 注 本文是基
  • AtomicInteger、Unsafe类、ABA问题

    AtomicInteger Java中的AtomicInteger大家应该很熟悉 它是为了解决多线程访问Integer变量导致结果不正确所设计的一个基于多线程并且支持原子操作的Integer类 AtomicInteger内部有一个变量UnS
  • Linux 中的 chroot 命令及示例

    Linux Unix系统中的chroot命令用于更改根目录 Linux Unix 类系统中的每个进程 命令都有一个称为root 目录的当前工作目录 它更改当前正在运行的进程及其子进程的根目录 在此类修改的环境中运行的进程 命令无法访问根目录
  • 巧用redis实现点赞功能,它不比mysql香吗?

    提到点赞 大家一想到的是不是就是朋友圈的点赞呀 其实点赞对我们来说并不陌生 我们经常会在手机软件或者网页中看到它 今天就让我们来了解一下它的实现吧 我们常见的设计思路大概分为两种 一种自然是用MySQL等数据库直接落地存储 另外一种就是将点
  • 常见linux服务器存储空间,怎么在linux上查看服务器的存储空间多大

    1 Linux下可以在 proc cpuinfo中看到每个cpu的详细信息 但是对于双核的cpu 在cpuinfo中会看到两个cpu 常常会让人误以为是两个单核的cpu 其实应该通过Physical Processor ID来区分单核和双核
  • 【linux系统编程】基础开发工具:vi/vim

    Linux文本编辑器 vim 正文开始 Assassin 目录 Linux文本编辑器 vim 1 vim基本介绍 2 vim下各模式的切换 3 vim命令模式 4 vim底行模式 5 vim可视化模式 6 额外补充 6 1 非法退出 6 2
  • 解密SVM系列(二):SVM的理论基础

    上节我们探讨了关于拉格朗日乘子和KKT条件 这为后面SVM求解奠定基础 本节希望通俗的细说一下原理部分 一个简单的二分类问题如下图 我们希望找到一个决策面使得两类分开 这个决策面一般表示就是 WTX b 0 W TX b 0 现在的问题是找
  • 如何进阶TypeScript功底?一文带你理解TS中各种高级语法

    引言 TypeScript 的重要性我不在强调了 我相信仍然会有大多数前端开发者碰到复杂类型一概使用 any 处理 我写这篇文章的目的就是为了让你告别 AnyScript 文章告别晦涩的概念结合实例来为你讲述一系列 TS 高级用法 分发 循
  • ipad横屏怎么设置方法,如何使ipad横屏

    ipad怎么设置横屏竖屏 具体如下 1 首先打开我们的平板 之后在屏幕上由下往上滑 如图 请点击输入图片描述请点击输入图片描述2 之后会出现一个菜单设置界面 点击选项右侧的 圆形 按钮 就可以锁定当前屏幕的方向 我们再点击一下就可以取消锁定
  • Golang协程,通道详解

    进程 线程以及并行 并发 关于进程和线程 进程 Process 就是程序在操作系统中的一次执行过程 是系统进行资源分配和调度的基本单位 进程是一个动态概念 是程序在执行过程中分配和管理资源的基本单位 每一个进程都有一个自己的地址空间 一个进
  • ChatGPT Sorry, you have been blocked(抱歉,您已被屏蔽)的解决方法

    最近在使用 ChatGPT 时大家遇到的最多的问题就是 Sorry you have been blocked 抱歉 您已被屏蔽 了 之前的 Access denied 似乎都不常见了 今天老王就分享下这个问题的原因和解决方法 一 Chat
  • 两年外包生涯做完,感觉自己废了一半....

    先说一下自己的情况 大专生 17年通过校招进入湖南某软件公司 干了接近5年的点点点 今年年上旬 感觉自己不能够在这样下去了 长时间呆在一个舒适的环境会让一个人堕落 而我已经在一个企业干了五年的功能测试 已经让我变得不思进取 谈了1年的女朋友
  • java 微信提现(复制即用)

    微信的支付是麻烦 但支付很简单 直接上代码 有详细注释 一共四个文件 重点 调用微信提现 import back minsu configure Token import back minsu param TiXianParam impor
  • 局部变量作为返回值

    一般来说 函数是可以返回局部变量的 局部变量的作用域只在函数内部 在函数返回后 局部变量的内存已经释放了 因此 如果函数返回的是局部变量的值 不涉及地址 程序不会出错 但是如果返回的是局部变量的地址 指针 的话 程序运行后会出错 因为函数只