C语言 跨函数使用内存.
1. 函数执行完成时,里面的局部静态变量所占的内存会被自动释放
首先看个简单的例子程序:
#include <stdio.h>int f(){int j=20;return j;
}int main(){int i;i = f();return 0;
}
可以见到上面 main函数 调用了f()函数, 而f()里面定义了1个整形变量j.
问题是, 如果f()被调用完成后, 也就是 i=f(); 这条语句执行完后, f()里面的j所占的内存还存在吗?
答案是否. 首先j是1个局部变量, 而且j是1个静态分配变量, 所以当f() 结束时, f()里面的局部静态分配内存的变量所占的内存都会被自动释放.
注意静态分配内存的变量不一定是静态变量(static 前序)
如果不释放有什么后果? 假如f() 在不同的地方被调用了1000次, 那么里面的j就占用了4byte * 1000 接近4MB的内存, 可用内存就会越来越少.
2. 内存空间传递的方式--内存头部字节的地址(指针)
那么main() 函数有无可能使用f函数定义的内存空间呢?
上面讲到, 局部静态分配内存变量肯定不行了, 因为一旦f() 被执行完. 里面的静态分配内存的变量所占内存会被释放嘛...
那么假如f() 里面分配了1块内存(连续的), 如果main函数要获得内存的内容, 则必须获得这块内存的地址, 我们知道内存里每1个单元都有1个内存地址. 因为这块内存是物理连续的, 我们之需要获得内存头部地址就ok了
那么f() 怎么把地址穿给main呢?
第一步肯定是 在mian里定义1个指针, 用于接受这个地址.
第二步呢?
3. 三个利用函数给指针赋值的例子.
就如一条选择题. 下面3个程序能能给main里的指针p 获得1个合法的变量地址呢?
A)
void f(int *q){int j=20;q=&j;
}int main(){int *p;f(p); return 0;
}
我们先看看例子A, 在main函数里定义1个 指针变量p, 然后把指针变量p作为参数传递给f, 然后f里面给这个参数赋值..
首先main函数里的变量p 本身就是1个指针变量, 而f的形参也是指针变量, 所以这个传递实际上是按值传递
稍稍有点编程基础的都知道按值传递的是形参的值是修改不了的. 所以p 作为参数被f(p)执行完. p的值是不变的.
A是错误的.
B)
void f(int ** q){int j=20;*q=&j;
}int main(){int *p;f(&p); return 0;
}
我们来看看B, 见到main是以指针p本身的地址(不是指向的地址)(&p)穿给f, f函数里面把变量j的地址传给了p本身
q = &p ==> *q =(*&p)= p
所以p的值的确被改变了.
那么B选项是正确的吗?
的确p通过f函数获得了1个地址.
但这个地址是j的地址, 而j是1个局部静态分配内存的变量啊, 上面说过,当 f被执行完. j就会被释放.
也就是虽然p获得了j的地址, 但是j本身被释放了, 所以也不是1个合法的变量地址.
B也是错误的.
C)
#include <stdlib.h>
void f(int ** q){*q = (int *)malloc(sizeof(int));**q = 20;
}int main(){int *p;f(&p); return 0;
}
C..
使用了动态分配内存, 在f函数分配了1个长度为1个int整形长度的内存(4字节), 然后把这个内存的头部地址穿给p.
那么在main里面能否使用这块内存?
答案是可以的啊, 因为在f函数里面. *q 也就是p 指向的内存并没有被手动释放啊..
所以C是正确的
由C这个例子我们可以看出两点:
1) 利用动态分配内存就可以实现跨函数使用这块内存了, 前提是这块内存未必释放.
2) 利用malloc 动态分配的内存, 最终必须手动释放内存.
如果忘记了释放有什么后果, 那么一般要等到程序结束时才会释放这块内存了.
其实也不一定, 我们平时使用操作系统时是不是觉得越用内存越少?
实际上很多操作系统都是由c/c++写成了, 如果程序员忘记手动释放内存, 就会导致内存泄露... 可用内存就越来越少.
4. 1个稍稍复杂一点的跨内存使用的例子
其实也不是很复杂啦,
下面这个小程序我们会定义1个create_list()函数.
利用create_list函数划分1个内存, 传给其他函数.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct Student * Create_list();
void memory_1();
void Show_list();int memory_main(){memory_1(); printf("memory main done\n");return 0;
}struct Student{int sid;int age;char name[100];
};void memory_1(){struct Student * p = Create_list();p->sid = 11; p->age = 24; strcpy(p->name,"JasonPoon");Show_list(p);
}struct Student * Create_list(){struct Student * pst;pst = (struct Student *)malloc(sizeof(struct Student)*1);return pst;
}void Show_list(struct Student * pst){printf("sid is %d, name is %s, age is %d\n",pst->sid, pst->name, pst->age);
}
输出:
gateman@GMPC Main $ ./main
sid is 11, name is JasonPoon, age is 24
memory main done
C语言 跨函数使用内存.相关推荐
- c语言字体移动函数,C语言字符函数、内存函数功能及实现代码
C语言字符函数.内存函数 功能及实现 strlen函数(求字符串长度)注意点模拟实现 strcpy函数(字符串拷贝函数)注意点模拟实现 strcat函数(字符串衔接函数)注意点模拟实现 strcmp函 ...
- c语言指针跨函数使用内存
#include <stdio.h> #include <malloc.h>//动态内存跨函数使用 void f(int ** q) {int j = 20;printf(&q ...
- C语言—字符串函数和内存函数
文章目录 1.前言 2.字符串函数 2.1 长度不受限制的字符串函数 2.1.1 strlen 内部细节 使用方法 模拟实现 2.1.2 strcmp 内部细节 使用方法 模拟实现 2.1.3 str ...
- C语言字符串函数,内存函数讲解及其模拟
在这篇博客会讲解以下函数:strlen,strcpy,strcat,strcmp,strncpy,strncat,strncmp,strstr,strtok,memcpy,memmove,memset ...
- C语言 memset()函数(内存初始化函数)
文章目录 描述 声明 参数 返回值 实例 描述 C 库函数 void *memset(void *str, int c, size_t n) 复制字符 c(一个无符号字符)到参数 str 所指向的字符 ...
- C语言memmove()函数: 复制内存内容(可以重叠的内存块)
头文件:#include <string.h> memmove() 用来复制内存内容,其原型为: void * memmove(void *dest, const void *src, s ...
- java跨函数跳转_C语言中将绝对地址转换为函数指针以及跳转到内存指定位置处执行的技巧...
1.方法一 要对绝对地址0x100000赋值,我们可以用 (unsigned int * ) 0x100000 = 1234; 那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做? ...
- 多级指针和静动态内存的跨函数访问
参考:多级指针(静动态内存的跨函数访问) 作者:枕上 发布时间:2021-07-15 00:27:17 网址:https://blog.csdn.net/jinchi_boke/article/det ...
- 关于c语言字符串函数和一些内存函数的的简介
关于c语言字符串函数和一些内存函数的的简介 求字符串长度的函数 strlen函数介绍![在这里插入图片描述](https://img-blog.csdnimg.cn/20190301142458376 ...
最新文章
- pandas使用iloc函数将dataframe的所有数据行反序(reverse the order of rows in dataframe)
- 斯坦福重磅报告:2030年的人工智能与生活
- 浏览器的渲染原理简介
- python工程师需要考什么证_考垃圾处理清运工程师证哪里颁发的今年的考试时间即将告知...
- 苹果赢了!iOS14隐私功能并不违反法国反垄断法
- 中国天然玉米黄质市场趋势报告、技术动态创新及市场预测
- windownavigatorscreenlocation
- java 合并两个列表_如何在Java中合并两个列表?
- 动态插入图片到 svg 中
- 学习笔记--数据结构与算法基础(青岛大学-王卓)--第六章图
- android隐藏顶部导航栏,Android去除顶部导航条
- S5P6818 芯片手册 DMA 章节 理论篇 重排
- 前端框架Vue(11)——Vue+表单验证 VeeValidate 实践
- python 入门书籍-入门python有什么好的书籍推荐?
- java没思路_Java编程没思路写不出代码怎么办
- FTP用户登录不成功
- Apowersoft Streaming Audio Recorder(录音精灵)官方中文版V4.3.5.2 | Apowersoft录音精灵官方下载
- 计算机专业个人评定,计算机专业个人自我鉴定
- python ansys workbench联动_【干货】经典ANSYS 与 Workbench如何实现联合仿真,相互切换操作。...
- 怎样才能去掉图片锁定纵横比_航旅纵横用户遭骚扰:相比社交搭讪,用户更在乎隐私...