zoukankan      html  css  js  c++  java
  • 深入理解C语言-深入理解内存四区

    数组与指针

    当数组做函数参数的时候,会退化为一个指针
    此时在函数内是得不到数组大小的
    因此,数组做函数参数的时候需要传递数组大小,也就是多传递一个参数

    void func(int arr[], int num)
    {
        ···
    }
    

    若存在以上函数,c/c++编译器在编译的时候,会将数组优化为一个指针,指向数组的首地址,因此无法通过sizeof获得数组大小
    以下可看作是c/c++编译器的优化过程
    int a[10] => int a[] => int *p

    void func(int *p, int num)
    {
        ···
    }
    

    实参与形参

    在函数调用的时候,实参的值机械的传递给形参
    形参:

    • 写在函数里面和函数上边,对C/C++编译器没有区别
    • 写在函数上边多了对外属性
    • 入栈时候从右至左入栈

    数据类型的本质

    数据类型
    按照上图,数据类型又可分为简单数据类型和复杂数据类型
    简单数据类型和复杂数据类型的处理方式不一样
    在处理复杂数据类型的时候,不能按照简单数据类型的处理方式去处理
    例如,存在 int a[10] 数组,那么 &a 的值和 a 的值相同,但是 &a + 1a + 1 的值却不相同,原因是前者代表的是一个数组地址,后者代表的是一个元素地址,前者加一,指出数组,而后者加一则是相当于指向下一个元素的地址,前者移动 sizeof(a) 字节,后者移动 sizeof(int) 字节
    C语言规定数组名代表数组首元素地址,&a代表整个数组
    数据类型的本质就是告诉编译器开辟内存的大小,就是一个指明开辟内存大小的说明性标签,也就是创建变量的模具,是固定内存大小的别名

    数据类型的大小和别名

    在C语言中,专门有一个操作符sizeof用来得到数据类型的大小,其大小在编译时候便已经确定
    由于数据类型只是一个标识,故可以使用typedef定义别名

    变量的本质

    既能读又能写的内存对象,称为变量;若一旦初始化后不能修改的对象则称为常量
    变量本质:(一段连续)内存空间的别名,标号

    • 程序通过变量来申请和命名内存空间
    • 通过变量名访问内存空间
      由于变量的本质就是内存空间的别名,故要修改变量的值,无外乎就两种方式
    • 直接:通过变量名,也就是别名修改
    • 间接:内存有地址编号,拿到地址编号也可以修改内存
    • 引用修改(C++)
      变量三要素(名称、大小、作用域)
    1. 对内存可读可写
    2. 通过变量向内存中读写数据,而不是像变量读写数据
    3. 向变量代表的数据空间读写数据

    数据类型和变量的关系

    C语言规定:通过数据类型,定义变量

    内存四区

    内存四区模型
    流程说明

    1. 操作系统把物理硬盘代码load到内存
    2. 操作系统把c代码分成四个区
    3. 操作系统找到main函数入口执行
    区块 作用
    栈区(stack) 由编译器自动分配释放,存放函数的参数值,局部变量的值等
    堆区(heap) 一般由程序员分配释放(动态内存申请与释放),若程序员不释放,程序结束时可能由操作系统回收
    全局区(静态区)(static) 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,该区域在程序结束后由操作系统释放
    常量区 字符串常量和其他常量的存储位置,程序结束后由操作系统释放
    程序代码区 存放函数体的二进制代码

    函数调用模型

    main()调用fa(),fa()调用fb()
    函数调用模型
    主调函数分配的内存,可以在被调函数中使用(指针做函数参数)
    在fa(),fb()中分配的内存,如果实在栈区,不可在main()中调用,如果在堆区,全局区,可以在main()中调用,注意内存的释放问题
    在被调用的函数中malloc的内存,首地址传递给调用函数有两种方法

    1. return
    2. 指针做函数参数

    内存四区和函数调用变量传递

    一个单进程主程序有n个函数组成,C++编译器只会分配一个堆区,一个栈区

    堆栈属性说明

    栈(stack):向下生长
    堆(heap):向上生长
    Heap、stack生长方向和内存存放方向是两个不同概念

  • 相关阅读:
    Unable to open the physical file xxxx. Operating system error 2
    Apache Solr 实现去掉重复的搜索结果
    solr调用lucene底层实现倒排索引源码解析
    lucene-solr本地调试方法
    lucene实战--打分算法没有那么难!
    avalon新一代UI库发布
    让 IE6支持max-height
    迷你MVVM框架 avalonjs 1.3.2发布
    less gradient-vertical 方法的实现
    sass compact方法的实现
  • 原文地址:https://www.cnblogs.com/cj5785/p/10664764.html
Copyright © 2011-2022 走看看