C语言——内存管理

内存管理

1.作用域

(1)文件作用域:全局变量,定义在函数外面的变量
int a=10;
void main(){
    int a = 20;   // 函数内部可以再次定义和全局变量同名的变量,定以后a为20,没有定义为10
    printf("%d\n", a);   
}
(2)extern关键字

c #include "c.h" // 在这个文件中定义了age=10 extern int age ; // 声明该变量在其他文件中定义了,连接时使用就可以了。这文件需要是.c文件,不能是.h文件。gcc编译时后面加上两个文件名 setage(int n){ age = n; } getage(){ printf("%d\n", age); } void main(){ setage(11); getage(); // 11 }

(3)auto自动变量:不写auto,就默认为auto变量
(4)register 变量:建议变量放到空闲的寄存器中:寄存器变量不能取地址操作
(5)static 变量:只初始化一次,程序运行期间一直存在 。static只是增大了变量的存在时间,却没增大变量的作用域

一旦全局变量被static修饰,则这个变量的作用域被限制在该文件内部,其他文件不能用extern使用
c void mystatic(){ static int a = 0; // 不加static,循环打印每次打印都是0,加上static每次打印+1 printf("%d\n", a); a++; } void main(){ for (int i = 0; i < 10; ++i) { mystatic(); } }

2.C语言中,函数都是全局的。

(1)如果函数前面加了static,则函数被限制在文件内部使用
(2)函数前面加不加extern一样。而变量前面的extern是可以省略的,比如:int a; 如果其他文件中定义了int a=10,则此处的变量是声明,如果其他文件中没有定义a,则此处是定义
(此处也是说明c语言并不严谨)

3.c语言内存管理

程序在内存中分为4个区域:

(1)栈:

不会很大,栈空间是操作系统为每个程序固定分配的大小以k为单位。栈空间是操作系统为每个程序固定分配的大。此部分的内存表现为先进后出。所有自动变量,函数行参都有编译器自动放到栈中。当一个自动变量超出其作用域时,自动从栈中弹出。先进入栈中的变量放到大内存号中
每个线程都有自己的栈

int main(){
    char array[1024*1024*1024] = {0};   //定义一个超大的数组就会栈溢出
    return 0;
}
(2)堆:

堆没有大小限制,只是无力限制。但是堆内存不能由编译器自动释放

#include <stdlib.h>
int main(){
int p = malloc(sizeof(int)10); // 在堆中申请了10个int的大小
char p2 = malloc(sizeof(char)10);

 memset(p,0,sizeof(int)*10);  // malloc申请的堆内存 ,在代码的操作上相当于数组
 for(int i=0;i<10;i++){ 
     p[i] = i;  // 操纵数组
 }

 free(p) ; // 释放通过malloc申请的堆内存
 free(p2);
}
(3)静态区:

所有的全局变量,以及程序中的静态变量都存储在静态区 (4)代码区:程序在被操作系统加载到内存中时,所有可执行代码加载到代码段,这块内存不能再程序运行期间修改c

int c= 0;
void main(){
int a=1;
int b=2;
static int d = 3;
printf("%d,%d,%d,%d,%d\n", &a,&b,&c,&d,main); // 1321929276,1321929272,6295612,6295604,4195632
}

上述程序的a和b在栈区,所以地址号紧挨着:1321929276,1321929272 发现a所在的内存号在高位。
c和d在静态区:地址号紧挨着
main在代码段

4.堆栈的一些问题

(1)不能将一个栈变量的地址作为函数的返回值,因为函数结束后,栈变量被释放

c eg: int *geta(){ int a = 10; return &a; }

(2)但是可以把堆变量的地址作为函数返回值返回
int geta(){
int p = malloc(sizeof(int));
return p;
}

int main(){
int p = geta();
malloc(p);
}
(3)不能用变量声明一个数组长度,eg:int arr[i], 如果申请内存的大小靠程序运行期间决定,那么就要使用 malloc(sizeof(int)*i),要记得free
(4)代码区和静态区的大小都是固定的,静态区是编译器根据代码提前申请的。堆和栈所占大小是动态,但是栈有一个操作系统规定的栈上线shell

cd /proc # 每个进程号都是一个文件
cd pid
cat maps # 查看内存映射,这里列出了代码段,堆,栈,静态区的使用情况(栈的预设范围)

(5)堆的分配 操作系统分配内存的单位不是字节,而是页。cat smps之后,发现堆有个项是内存页大小:4k。页太大,浪费的内存空间太大,但操作系统维护起来很简单,因为不用频繁的申请释放内存
</br>
(6)malloc申请的堆内存上会存在旧数据,所以申请后需要用memset清空 :memset(p,p,sizeof(int)*10) 这两句话的简写就是calloc,这样内存上全部是0
int main(){
char p = calloc(10,sizeof(char)); // 申请大小是10sizeof(char)
}
(7)relloc用于扩展已经申请的堆内存,在原有内存上,增加连续的内存,如果没有连续空间可扩展,则会新分配一个连续空间,将原有内存拷贝到新空间,然后释放原有内存。但是relloc只申请,不打扫(内存中有旧数据)

// rello(p,新的内存大小),.如果p为NULL,则realloc等于malloc,不指定分配空间的起始位置

void main(){
char p1 = calloc(10,sizeof(char));
char *p2 = realloc(p1,5); // p1指向的地址变为5
// realloc(NULL,5) = malloc(5)
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • 第八章 内存管理 8.1 作用域 C语言变量的作用域分为: 代码块作用域(代码块是{}之间的一段代码) 函数作用域...
    CodeDove阅读 327评论 0 1
  • 前言 C语言作为一门应用途广泛、功能强大、使用灵活的面向过程式编程语言。既可用于编写应用软件,又能用于编写系统软件...
    老板娘来盘一血阅读 12,960评论 32 83
  • 谨记 人生有两条路,一天需要用心走,叫做梦想;一条需要用脚走,叫做现实。心走的太快,会迷路的;脚走的太快,会摔倒的...
    长风留言阅读 5,909评论 7 16
  • 对于一个C语言程序而言,内存空间主要由五个部分组成代码段(.text)、数据段(.data)、BSS段(.bss)...
    朱森阅读 384评论 0 0
  • 本来写完老爸老妈,该写老公,可偏偏有人要加塞,不答应就要代表人民枪毙我,在她的威逼利诱下,就破坏一下长幼有...
    行走的鹿阅读 696评论 0 0