注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

饥民2011

一直在搬砖

 
 
 

日志

 
 
 
 

C语言 跨函数使用内存.  

2013-04-01 00:24:14|  分类: c/c++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |


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.
那么在mian里面能否使用这块内存?

答案是可以的啊, 因为在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



  评论这张
 
阅读(269)| 评论(5)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017