跨函数使用内存空间

所谓动态内存分配(Dynamic Memory
Allocation)就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。凡是在程序中用到系统提供的动态分配存储空间函,均要求包含头文件<malloc.h>。

Malloc 向系统申请分配size字节的存储区。返回分配内存空间的起始地址,若分配失败,则返回0,类型是 void*
(或chaar*)、malloc(size)、unsigned size类型。void* 表示未确定类型的指针,void
*可以指向任何类型的数据,更明确的说是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据(比如是char还是int或者...)。C,C++规定,void*
类型可以强制转换为任何其它类型的指针。

1、为什么需要动态分配内存

首先介绍一下传统数组的缺点,这里的传统数组也叫静态数组,传统数组的缺点:

1>.数组长度必须事先定制,切只能是长整形,不能是变量;

2>.传统形式定义的数组,该数组的内存程序员无法手动释放;

3>.数组的长度一旦定义,其长度无法更改;

4>.传统形式定义数组不能跨函数使用。

以上传统数组的四点缺陷,动态数组能够很好的解决这四个缺陷,所以我们需要动态分配内存。

2、malloc的使用:

malloc是memory(内存) allocate(分配)的缩写

#include<stdio.h>

#include<maiioc.h> //使用动态分配空间函数,必须添加malloc.h头文件

int main(void)

{

int i=5;  
//分配了4个字节 静态分配

int * p=(int
*)malloc(4);   //12行

/*1、要使用malloc函数,必须添加malloc.h头文件

2、malloc函数只有一个形参,并且形参是整数

3、4表示请求系统为本程序分配4个字节

4、malloc函数只能返回第一个字节的地址

5、12行分配了8个字节,p变量占4个字节,p所指向的内存也占4个字节

6、p本身所占的内存是静态分配的,p所指向的内存是动态分配的

*/

* p=5;  //*p代表的就是一个int变量,只不过*p这个整形变量的内存的分配方式与(int
i=5)的i的分配方式不同。

free(p);   //free(p)表示把p所指向的内存给释放掉,p本身的内存是静态的,不能有程序员手动释放,p本身的内存只能在p变量所在的函数运行终止后有系统自动释放。

printf("How are you!\n");

return 0;

}

 3、动态内存分配举例

#include<stdio.h>
#include<malloc.h>
int
main(void)
{
  int a[5]; //如果int占四个字节的话,则本数组总共包含20个字节,每个字节被当做了一个int变量来使用
 
int len;
  int * pArr;
  int i;
  //动态的构造一维数组名
  
printf("请输入你要存放的元素个数:");
   scanf("%d",&len);
  
pArr=(int *)malloc(4 * len);   /*本行动态的构造了一个一维数组,该数组的长度是len,该数组的数组名是pArr,
                                                   该数组的每个元素师int类型,类似于int
pArr[len];*/
 
  //对一维数组名进行操作。如:对动态一维数组进行赋值
 
for(i=0;i<len;++i)
     
scanf("%d",&pArr[i]);
  //对一维数组进行输出
 
printf("一维数组的内容是:\n");
 
for(i=0;i<len;++i)
    
printf("%d\n",pArr[i]);
  free(pArr);    //释放掉动态分配的数组
  return 0;

}

4、动态数组的构造

5、free(p)的使用

表示把p所指向的内存释放掉,p本身的内存是静态的,不能有程序员释放掉,p本身的内存只能在p变量所在的函数运行终止后有系统释放。
6、静态、动态内存分配比较

1). 静态内存分配是在编译时完成的,不需要占用CPU资源;动态分配内存是在运行时完成的,动态内存的分配与释放需要占用CPU资源;
2)
.静态内存分配是在栈上分配的,动态内存是堆上分配的;
3) .动态内存分配需要指针或引用数据类型的支持,而静态内存分配不需要;
4)
.静态分配内存需要在编译前确定内存块的大小,而动态分配内存不需要编译前确定内存大小,根据运行时环境确定需要的内存块大小,按照需要分配内存即可。可以这么说,静态内存分配是按计划分配,而动态内存分配是按需分配。
5)
.静态分配内存是把内存的控制权交给了编译器,而动态内存是把内存的控制权交给了程序员;

综上所述,静态分配内存适合于编译时就已经可以确定需要占用内存多少的情况,而在编译时不能确定内存需求量时可使用动态分配内存;但静态分配内存的运行效率要比动态分配内存的效率要高,因为动态内存分配与释放需要额外的开销;动态内存管理水平严重依赖于程序员的水平,如果处理不当容易造成内存泄漏。

7、如何选择内存分配方式

1>. 全局变量尽可能不要动态分配内存。

2>. 动态分配内存时,分配与释放的代码要对称。

3>. 对动态创建的对象或分配的内存块一定要检查期有效性。

4>. 尽可能少次数地使用动态内存分配。

5>. 在保证资源利用率的前提下,能用静态内存分配不用动态分配,特别是局部临时对象。

总结:静态内存是有系统自动分配的,由系统自动释放,静态内存是在栈分配的;动态内存是由程序员分配的,手动释放,动态内存是在堆分配的。

8、跨函数使用内存的问题

1>.静态变量不能跨函数使用内存

/* 此代码是错误的,目的是为了演示静态变量不能跨函数使用静态内存由系统分配,当函数执行完毕由系统自动释放 */  
# include <stdio.h>
  
# include <stdlib.h>
  
void f(int ** q)  
{  
    /*q是指针变量,无论是什么类型的指针变量都只占4个字节 q=&p。q存放了p的地址 q存放的是int *类型的变量地址,q变量的类型是int **,*q的类型是int *。p存放的是int类型的变量地址,p变量的类型是int *,*P的类型是int。*q等价于p, p可以存放int类型变量的地址 */  
    int i=5;  
    *q=&i;  //等价于p=&i   
}  
int main (void )  
{  
    int * p;  
    f(&p);  
    /* f函数中的q变量和i变量的空间都是由系统分配的静态内存空间 
        属于静态变量,当f函数执行完毕后,系统自动释放 
        q和i所占用的内存空间,所以下面一行语句将无法访问 
        其数据。 
    */  
    printf("%d", *p); //本语句语法上没有问题,但逻辑上有问题   
    system("pause");  
    return 0;  
}

2>.动态内存可以跨函数使用内存 
/* 动态内存由程序员手动分配,手动释放 */  
#include <stdio.h>
  
#include <malloc.h>
  
#include <stdlib.h>   
void f(int ** q)  //q存放int *类型变量的地址   
{  
    //sizeof(数据类型)返回的是该数据类型所占的字节数。
  
    //此处最好不要写成4,因为不同的机器它的数据类型所占的字节数有可能不相同   
    *q=(int *) malloc(sizeof(int)); //等价于p=(int *) malloc(sizeof(int));
  
    //q=5;  //error
  
    //*q=5;//error p=5
  
    **q=5; //*p=5   
 }  
int main(void)  
{  
    int * p;  //p存放int *类型变量的地址   
    f(&p);  
    printf("%d\n",*p);  
    system("pause");  
    return 0;  
}  
// 动态内存由程序员手动分配,手动释放
#include
<stdio.h>
#include <malloc.h>
#include
<stdlib.h>

void f(int ** q)  //q存放int
*类型变量的地址
{
//sizeof(数据类型)返回的是该数据类型所占的字节数。
//此处最好不要写成4,因为不同的机器它的数据类型所占的字节数有可能不相同
*q=(int
*) malloc(sizeof(int));  //等价于p=(int *)
malloc(sizeof(int));
//q=5;//error
//*q=5;//error
p=5
**q=5; //*p=5
}
int main(void)
{
int
* p;  //p存放int
*类型变量的地址
f(&p);
printf("%d\n",*p);
system("pause");
return
0;
}

http://wljjiwang.blog.163.com/blog/static/54762512201422724922388/

跨函数使用内存空间

时间: 2024-11-05 23:27:21

跨函数使用内存空间的相关文章

6、跨函数使用内存

1.静态变量不能跨函数使用(重点) /*---------------------------------------------------------------------------------------- 静态变量不能跨函数使用 ------------------------------------------------------------------------------------------ 指针变量地址只能是**类型,这里q存放的是指针变量p的地址,那么*q就是p,

使用malloc和free函数进行内存动态分配

一.在学习c语言里面,内存分配这个话题非常有意思,因为我们平时在开发的时候,如果一不小心没注意内存释放的话,写的的程序很容易出错,所以今天就来回顾一下c语言里面的内存动态分配,下面我们先来看一个实例来进行分析 1 #include <stdio.h> 2 #include <malloc.h> 3 int main(void) 4 { 5 int a[5] = {4, 10, 2, 8, 6}; 6 int len; 7 printf("请输入数组的长度大小:len= &

L2--跨函数使用内存

介绍 #include <stdio.h>#include <malloc.h> int main(void) { int *p; //定义了一个指针变量,但并没有为期附初值:下面两个函数都是为其fu初值的操作 f(&p); //f函数,为指针变量p附了一个准确的值,所以是正确的操作 //g(&p);//g函数,虽然在g函数执行过程中未p附了一个准确的值,但g函数执行结束后指针变量的值,并非是一个准确的值 return 0; } void f(int ** q) {

动态内存可以跨函数使用示例与静态变量不能跨函数使用

动态内存可以跨函数使用示例 # include <stdio.h> # include <malloc.h> void f(int ** q) { *q = (int *)malloc(sizeof(int)); //sizeof(数据类型) 返回值是该数据类型所占的字节数 //等价于 p = (int *)malloc(sizeof(int)); //q = 5; //error //*q = 5; //p = 5; **q = 5; //*p = 5; } int main(v

PostgreSQL 聚合函数共享申请的内存空间

CREATE AGGREGATE Rbitmap_union2 (Rbitmap) ( sfunc = myfunction, stype = mytype, FINALFUNC = myfunction_final ); 在编写聚合函数时,对每一行都会重复调用指定同一函数,如果要处理的数据是累加的,那么如果不在每次调用之间共享内存空间,而是不停的申请释放新的内存,那么速度会变得很慢,所以在这时共享内存是十分有用的: PostgreSQL 有 MemoryContext 的概念,如果普通的使用

linux函数深入探索——open函数打开文件是否将文件内容加载到内存空间

转自:https://blog.csdn.net/qq_17019203/article/details/85051627 问题:open(2)函数打开文件是否将文件内容加载到内存空间 首先,文件打开后都会产生一个文件描述符fd,这个文件描述符其实是记录在PCB的文件描述符表中,而这个文件描述符实质上是一个结构体,用来存放跟打开文件相关的信息,基于此前提,我产生了两种假设 1.文件描述符结构体中只存储了文件在硬盘中的相应地址信息,并不将文件内容加载到内存中,这样做的好处是减少内存空间的占用,但大

C语言中free函数是如何确定要释放多少内存空间的

本文链接:http://www.cnblogs.com/xxNote/p/4009359.html 今天看书的时候看到free函数释放动态申请的内存时只需要把内存块的首地址传过去就行了,显然仅仅依靠首地址是无法确定要释放多少内存的,猜想应该在某处存放着这个内存块的大小,网上搜了搜发现在Linux里面glibc在分配内存的时候会在内存块的地址前面的4个字节出存放内存块的大小,就猜想Windows里面应该也是这样.写了一个小程序测试了下: #include <stdio.h> #include &

函数嵌套 ,名称空间与作用域 ,闭包函数 ,装饰器 ,迭代器, 生成器 三元表达式,列表解析,生成器表达式 递归与二分法, 内置函数

函数嵌套名称空间与作用域闭包函数装饰器迭代器生成器三元表达式,列表解析,生成器表达式递归与二分法内置函数--------------------------------------------函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数def max(x,y): if x>y: return x else: return ydef max1(a,b,c,d): res=max(a,b) res2=max(res,c) res3=ma

Linux内存点滴:用户进程内存空间

原文出处:PerfGeeks 经常使用top命令了解进程信息,其中包括内存方面的信息.命令top帮助文档是这么解释各个字段的.VIRT , Virtual Image (kb)RES, Resident size (kb)SHR, Shared Mem size (kb)%MEM, Memory usage(kb)SWAP, Swapped size (kb)CODE, Code size (kb)DATA, Data+Stack size (kb)nFLT, Page Fault countn