C语言灵魂篇|指针作为函数返回值
C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。下面的例子定义了一个函数 strlong(),用来返回两个字符串中较长的一个:
#include
#includechar *strlong(char *str1, char *str2){
if(strlen(str1) >= strlen(str2)){
return str1;
}else{
return str2;
}
}int main(){
char str1[30], str2[30], *str;
gets(str1);
gets(str2);
str = strlong(str1, str2);
printf("Longer string: %s\n", str);return 0;
}
运行结果:
C Language↙
c.biancheng.net↙
Longer string: c.biancheng.net
用指针作为函数返回值时需要注意的一点是,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针请尽量不要指向这些数据,C语言没有任何机制来保证这些数据会一直有效,它们在后续使用过程中可能会引发运行时错误。请看下面的例子:
#includeint *func(){
int n = 100;
return &n;
}int main(){
int *p = func(), n;
n = *p;
printf("value = %d\n", n);
return 0;
}
运行结果:
value = 100
n 是 func() 内部的局部变量,func() 返回了指向 n 的指针,根据上面的观点,func() 运行结束后 n 将被销毁,使用 *p 应该获取不到 n 的值。但是从运行结果来看,我们的推理好像是错误的,func() 运行结束后 *p 依然可以获取局部变量 n 的值,这个上面的观点不是相悖吗?
为了进一步看清问题的本质,不妨将上面的代码稍作修改,在第9~10行之间增加一个函数调用,看看会有什么效果:
#includeint *func(){
int n = 100;
return &n;
}int main(){
int *p = func(), n;
printf("c.biancheng.net\n");
n = *p;
printf("value = %d\n", n);
return 0;
}
运行结果:
c.biancheng.net
value = -2
可以看到,现在 p 指向的数据已经不是原来 n 的值了,它变成了一个毫无意义的甚至有些怪异的值。与前面的代码相比,该段代码仅仅是在 *p 之前增加了一个函数调用,这一细节的不同却导致运行结果有天壤之别,究竟是为什么呢?
前面我们说函数运行结束后会销毁所有的局部数据,这个观点并没错,大部分C语言教材也都强调了这一点。但是,这里所谓的销毁并不是将局部数据所占用的内存全部抹掉,而是程序放弃对它的使用权限,弃之不理,后面的代码可以随意使用这块内存。对于上面的两个例子,func() 运行结束后 n 的内存依然保持原样,值还是 100,如果使用及时也能够得到正确的数据,如果有其它函数被调用就会覆盖这块内存,得到的数据就失去了意义。
第一个例子在调用其他函数之前使用 *p 抢先获得了 n 的值并将它保存起来,第二个例子显然没有抓住机会,有其他函数被调用后才使用 *p 获取数据,这个时候已经晚了,内存已经被后来的函数覆盖了,而覆盖它的究竟是一份什么样的数据我们无从推断(一般是一个没有意义甚至有些怪异的值)。
声明:
本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。
C语言灵魂篇|指针作为函数返回值相关推荐
- C语言指针作为函数返回值
C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数.下面的例子定义了一个函数 strlong(),用来返回两个字符串中较长的一个: #include <stdio.h> ...
- C指针7:指针作为函数返回值
C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数.下面的例子定义了一个函数 strlong(),用来返回两个字符串中较长的一个: #include <stdio.h> ...
- 使用指针做函数返回值
使用指针做函数返回值 1.当使用指针做为函数的返回值时,主函数处的char *p;将获得调用函数char *pf;的值,即一个地址值,如oxAE72.此时需要我们注意的是该地址值所指向的空间是否存在( ...
- 7 C++指针做函数返回值
在C++中,函数的返回值出来可以是普通的数据类型,还可以是指针类型,我们将函数的返回值定义为指针类,用来返回一个变量的地址,但我们不能返回局部变量的地址. 用指针作为函数返回值时,需要注意的一点是,函 ...
- C语言中未显示声明函数返回值的类型
C语言中如果未显示声明函数返回值的类型或函数的形式参数类型,它就默认返回整型.这种声明在C语言中叫做隐式声明.例如: / //main.c /#include<stdio.h>divide ...
- C语言中连续调用rand函数,返回值不变
C语言中连续调用rand函数,返回值不变 最近用C语言随机函数编程发现了一个奇怪的现象: 简易版代码: #include<stdio.h> #include<stdlib.h> ...
- c语言函数返回值可以是字符串吗,函数返回值可以是字符串吗
c语言中函数返回值可以是数组.字符串和结构体吗? 因为在C语言中函数不能返回数组,但字符串是存储在字符数组中的,所以能C语言中实现函数返回字符串,首先要确定函数返回的字符串地址的来源,一般分为四种方式 ...
- 【C 语言】字符串模型 ( 字符串翻转模型 | 抽象成业务函数 | 形参返回值 | 函数返回值 | 函数形参处理 | 形参指针判空 )
文章目录 一.字符串翻转模型 业务函数 二.完整代码示例 一.字符串翻转模型 业务函数 将上一篇博客 [C 语言]字符串模型 ( 字符串翻转模型 ) 的代码 , 主要业务逻辑 , 抽象成函数 ; 字符 ...
- c语言指针,return以及函数返回值
指针作为c语言的精华所在所以会多学习几天来扎实的掌握 void* 这不叫空指针,这叫无确切类型指针.这个指针指向一块内存,却没有告诉程序该用何种方式来解释这片内存.所以这种类型的指针不能直接进行取内容 ...
最新文章
- cassandra命令
- javaswing引入百度地图_【react】React怎么引用百度地图
- 机器学习理论《统计学习方法》学习笔记:第九章 EM算法及其推广
- 昨晚三巨头聚餐,顺便聊了这三个问题
- arduino 上传项目出错_Arduino多核编程:简单例子
- ASP.NET Literal控件用法
- EM算法极其推广---EM算法的收敛性
- 10右键闪退到桌面_windows7多用户远程桌面如何设置
- Spring框架----Spring常用IOC注解的分类
- C++中实现类似php的UTF8和UrlEncode函数的代码
- mongodb的常用增删改查命令:
- asp 加密 解密 类
- webstorm绝对路径引入echarts_Webstorm+Webpack+echarts构建个性化定制的数据可视化图表两个echarts详细教程(柱状图,南丁格尔图)...
- 联想进入bios修复计算机,联想笔记本安装win10后开启界面一直是自动修复,进不了BIOS重装系统...
- 创宇云蜜罐成为华为云联营商品,合力提供网络安全服务
- Git(二) Git基础入门与实践
- 崩坏3服务器修改水晶数量,崩坏3一个月能攒多少水晶_单月水晶数量分析
- macOS 安装lrzsz
- Vue3+TS 快速上手 (尚硅谷)
- 基于javaweb+mysql的农产品水果店销售管理系统
热门文章
- 使用Caffeine和Spring Boot的多个缓存配置
- spring消息队列_AmazonSQS和Spring用于消息传递队列
- netbeans7.4_NetBeans 7.4的本机Java打包
- 接口中的默认方法和静态方法
- lucene创建索引_Lucene概述第一部分:创建索引
- java java se_Java SE 7、8、9 –推动Java前进
- k8s secret使用_Java Secret:使用枚举构建状态机
- 不可将您的方法命名为“等于”
- 生成器设计模式的应用
- 通过Spring将继承树加载到List中