C语言的内存管理

来源:互联网 发布:淘宝开店策划方案 编辑:程序博客网 时间:2024/04/25 11:31


        当我们硬件资源很紧张的时候,内存的管理就显得尤为重要了。想对C语言的内存管理有个比较的好的了解,就让我先了解一下代码中那些东西与内存的关系最为直接、最为频繁,我的印象中,变量、函数与内存是分不开的。首先让我们来复习一下变量、函数的知识。

一  变量的类型:

    1. 全局变量:代码块之外的变量,全局变量一般是在.c中定义的,在.h用extern关键字声明的(定义只能是一次,声明是可以多次),如果其他.c文件想用就可以调用这个.h就行。还有另外几种方法来实现全局变量在多个.c文件共享。

    2. 静态变量:static关键字修饰的变量,静态变量有2种,一种是代码块之外的静态变量,这个是变量的只是本文件可用,代码块之内的静态变量,只能被代码块内所使用             

    3.局部变量:代码块内部的变量,没有任何的修饰符,实际这些变量的隐藏的修饰符是auto

    变量的一个很重要的性质作用域与内存的管理有很大的关系,作用域就是这个变量的生命周期、存在时间。

二 函数:函数默认都是全局的,当然也可以用static变量修饰,那么这个函数成了仅本文件有效。

三 内存管理:

    每一个应用程序都把所占用的内存分为了几个区域:下面就是分配示意图

#include <stdio.h>#include <string.h>#include <stdlib.h>int a = 10;//已经初始化的全局变量,数据段 int h;//未初始化的全局变量,bss段 static int b = 15;//全局static变量,数据段 int test(int x, int y);int main(void){int i = 0;//局部变量,栈 printf("&a = %p, a = %d, &b = %p, b = %d, &i = %p, i = %d, &h = %p, h = %d\n", &a, a, &b, b, &i, i, &h, h);int c = 1;printf("&c = %p, c = %d\n", &c, c);char *s ="hello";//s 存放栈,hello常量,数据段,所以s指向的内存在数据段 char *p = (char*)malloc(10);//堆 printf("&p = %p, p = %d, p = %s\n", &p, p, p);if (p != NULL){strcpy(p,s);}printf("&p = %p, p = %d, %s\n", &p, p, p);printf("c = %p, %s\n", s, s);i = test(a,c);printf("&i = %p, i = %d\n", &i, i);i = test(a,c);printf("&i = %p, i = %d\n", &i, i);if (p != NULL)//下面这段比较容易被忽视,但 {    free(p);    printf("&p = %p, p = %d, %s\n", &p, p, p);    p = NULL;    printf("&p = %p, p = %d, %s\n", &p, p, p);}return 0;}int test(int x, int y){static int d = 0;//数据段 printf("&d = %p, d = %d\n", &d, d);int e = 2;d += (x -y -e);return d;}



这些内存区分别都存了那些数据呢

1.代码段:存放cpu要执行的指令,通常都是只读,防止被修改。

2.数据段:已经初始化的全局变量,常量,静态变量。

3.bss段:未初始化的全局变量。

4.栈:是由编译器自动分配和释放的,存放的是一些局部变量和函数的参数。地址是向下生长的。每当函数被调用的时候,会把函数的返回地址和一些调用信息存放在栈区,再为函数的临时变量和参数在栈区申请内存。函数返回时,这些临时变量和参数的内存就会别销毁。

5堆:程序员自行分配和释放,不自行释放就会造成一些意想不到的bug,地址是向上生长的。

分了这么多区,编译器是基于什么呢,代码都是顺序执行,通过递归和跳转会重复执行一些代码,因为一些代码块会被重复使用,所以代码块里面申请的变量都放在栈里面,全局变量和静态变量一般在整个程序运行时期都要被访问。这样就可以节约内存。



0 0
原创粉丝点击