C程序内存的分配,const ,volatile,static

一个c/c++程序占用的内存分别位以下几个部分

1.栈区:由编译器自动分配释放,储存为函数而分配的局部变量,函数参数,返回数据,返回地址等,其操作方式类似于数据结构里的栈

2.堆区:一般由程序员手动分配释放,若程序员不释放程序结束时可能由OS回收。

3.全局区(静态区):由于存放全局变量,静态变量常量,程序结束后由系统释放

4.常量区:用于存储常量字符串

5代码区:用于存放函数体(类成员函数和全局函数)的二进制代码

这并不是真正的物理地址,一个计算机中可以有多个程序在运行,而每一个程序都有一个运行时堆栈,而物理内存只有一个,这只是一个虚拟地址

内存分配的三种方式:

1.从静态区分配:内存在程序编译的时候就已经分配好了,这块内存在程序的整个运行期间都存在,例如:全局变量,static变量

2.在栈上分配:效率高,但是栈的空间有限,执行时创建,执行结束后系统自动释放。栈时向下生长的,先定义的变量地址高,后定义的变量地址低,但是在栈上定义的数组的地址是由低向高的,因为数组一次性开辟一整块空间,然后分配给数组内的元素。

3.在堆上分配:也称为动态内存分配,堆是自下向上生长的,变量的地址一次增大。用malloc()或new()申请任意空间,程序员自己负责在何时用free()/delete()释放内存。动态内存的生命周期由程序员自己负责,使用非常灵活。但是一定要记得回收,不然可能会产生内存泄漏的问题。频繁分配、释放不同大小的空间还有可能导致内存碎片的问题。

const、volatile关键字

const:修饰变量,使变量具有常性。编译器会在编译时进行优化,将const变量放入寄存器

#include<stdio.h>
int main()
{
    const int num = 10;
    int *p = (int*)&num;
    *p = 20;
    printf("%d",num);
    return 0; 
}

//输出仍然为10 ,为什么呢?

编译器在编译期间会对代码进行优化,当编译器看到num被const修饰时,就会将num的值放在寄存器中(以提高访问的效率),以后只要使用num就会区寄存器里面取,所以即使改变了num对应的内存中的值,寄存器也感知不到,所以就会输出10。

但我们对代码做如下修改:

#include<stdio.h>
int main()
{
    volatile const num = 10;
    int *p = (int*)&num;
    *p = 20;
    printf("%d",num);
    return 0;
}

//这样对*p做修改时num就等于20,为什么呢?

volatile:保证内存的可见性,使编译器在编译时不进行优化,执行时不缓存,每次都去内存中读出。

static:

  • 修饰函数:改变其链接属性,由外部链接属性-->内部链接属性(函数只能在当前源文件内使用,不能在其他源文件内使用),存储类型(生命周期)和作用域不受影响
  • 修饰变量:

          1)全局变量:与修饰函数的作用一致,改变其链接属性(外->内),存储类型和作用域不受影响

          2)局部变量:改变其生命周期(存储类型),由自动变量变成了静态变量,作用域和链接属性不受影响

猜你喜欢

转载自blog.csdn.net/audience_fzn/article/details/81393369