程序在系统上运行时,会为程序分配内存,有堆区 栈区 全局区 代码区 我们主要介绍堆区和栈区
栈区
由于是C语言复习,我不会讲一些汇编的东西,所有在这里讲的都是基于内存图和栈这种数据结构。
我先写一段代码,然后将代码映射到内存图中去 简单明了
#include<stdio.h>
int total = 0;
int squareofsum(int a ,int b)
{
return square(a + b);
}
int square(int x)
{
return x * x;
}
int main()
{
int a = 4;
int b = 8;
total = squareofsum(a, b);
printf("output = %d", total);
}
C++首先,程序运行,栈分配给main函数内存空间,存放main函数的参数 变量以及返回值 total是全局变量 所以要存放在全局区。因为main函数中调用了函数sos ,栈将暂停当前的栈空间 继续开辟一块内存给sos函数使用 同理sauare函数继续开辟 当各个函数执行完成 栈空间依次清空每个函数的栈空间 最后执行到printf函数继续压栈。需要注意的是,栈空间并不是无限大的,而是有大小限制的,如果我们超过了栈的大小,就会导致溢出。
无限递归-一直在压栈 而没有清空栈 很快栈就会溢出
堆
栈是系统为内存自动分配和销毁的一种数据结构,而堆需要程序员手动分配和创建,因此也被叫做动态内存
为了使用动态内存,需要介绍几个堆的操作函数malloc calloc relloc freevoid* malloc (size_t size);
malloc() 在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。如果希望在分配内存的同时进行初始化,请使用 calloc()函数。
返回申请内存的首地址 否则返回NULL 原返回类型是未知类型的指针 我们可以转换成我们需要的指针通过强转
首先在栈区创建一个整型指针 然后用malloc在堆区申请一段4个字节的内存地址,并用p指向这段内存 然后通过free释放这段内存 需要注意的是free释放的是malloc申请的内存,并不是单纯的将指针置为NULL这么简单 可以注意的是free后的p指针依旧是存在的。
可以看出来第一次申请的内存地址被释放之后 第二次申请的内存地址和第一次是一样的,指针还是指向了这个内存
如何在堆中申请一块存放数组的空间
首先申请一个可以存放数组大小的内存空间
malloc(20*sizeof*(int)); 接着通过同类型指针的指向 就可以得到申请内存的首地址也就是数组的首地址 然后就可以进行指针运算