zoukankan      html  css  js  c++  java
  • C语言内存分布

    C语言内存分布

    典型的C语言程序内存表示分区共有5个部分:

    1. 正文段 Text segment
    2. 已初始化数据段(数据段)Initialized data segment
    3. 未初始化数据段(bss)Uninitialized data segment
    4. 堆 Stack
    5. 栈 Heap

    具体分布图

    memory layout

    各个分区的作用

    • 正文段
      • CPU执行的机器指令部分
      • 通常可共享
      • 常常是只读的
    • 已初始化数据段(数据段)
      • 包含程序中需明确赋初始值的变量
      • 保存已经初始化的全局变量
    • 未初始化数据段(BSS)
      • 在程序开始执行之前,内核将此段中的数据初始化为0或空指针
      • 保存未初始化的全局变量(注意:即使是赋值为0也是未初始化!
      • 存储自动变量(如函数形参)及每次函数调用所需保存的信息
      • 每次函数调用时,存放其返回地址及调用者的环境信息(如某些机器寄存器的值)
      • 为最近被调用的函数分配自动变量和临时变量的存储空间
      • 动态存储分配

    初始化?

    上面提到,对全局变量来说,如果是赋值为0仍是未初始化。下面给出实际实验结果:

    示例代码1

    
    #include <stdio.h>
    
    int a;
    
    int main(int argc, char const *argv[])
    {
        printf("hello
    ");
        return 0;
    }
    
    

    编译后查看内存分布:

    示例代码2

    
    #include <stdio.h>
    
    int a = 0;
    
    int main(int argc, char const *argv[])
    {
        printf("hello
    ");
        return 0;
    }
    
    

    编译后查看内存分布:

    可以看到,各个存储区域数值没有变化。

    示例代码3

    
    #include <stdio.h>
    
    int a = 1;
    
    int main(int argc, char const *argv[])
    {
        printf("hello
    ");
        return 0;
    }
    
    

    编译后查看内存分布:

    可以看到,对全局变量进行真正的初始化之后,bss少了4个字节,data段多出了4个字节。

    关于static的问题

    示例代码4

    先看看相对上一例子,多了一个局部变量之后的内存分布。

    
    #include <stdio.h>
    
    int a = 1;
    
    int main(int argc, char const *argv[])
    {
        int b;
        printf("hello
    ");
        return 0;
    }
    
    

    编译后查看内存分布:

    可以看到,内存分布是没有变化的,局部变量b会在栈上分配到内存。

    示例代码5

    如果把b定义成static呢?

    
    #include <stdio.h>
    
    int a = 1;
    
    int main(int argc, char const *argv[])
    {
        static int b;
        printf("hello
    ");
        return 0;
    }
    
    

    编译后查看内存分布:

    可以看到,此时bss上多出了8个字节。

    示例代码6

    如果给b赋初始值0呢?

    
    #include <stdio.h>
    
    int a = 1;
    
    int main(int argc, char const *argv[])
    {
        static int b = 0;
        printf("hello
    ");
        return 0;
    }
    
    

    编译后查看内存分布:

    可以看到,跟上一个例子相比没有变化,说明跟全局变量一样,static变量赋值为0仍是未初始化。

    示例代码7

    如果给b赋初始值1呢?

    
    #include <stdio.h>
    
    int a = 1;
    
    int main(int argc, char const *argv[])
    {
        static int b = 1;
        printf("hello
    ");
        return 0;
    }
    
    

    编译后查看内存分布:

    可以看到,bss少了4个字节,而data多了4个字节,说明静态变量和全局变量同理,初始化之后是存在data段中的。

    关于static的用处

    示例代码8

    
    #include <stdio.h>
    
    int x = 4;
    
    void incre() {
        static int x = 1;
        x *= x + 1;
        printf("%d
    ", x);
    }
    
    int main(int argc, char const *argv[])
    {
        int i;
        for (i = 1; i < x; i++) {
            incre();
        }
        return 0;
    }
    
    

    运行结果为:

    可以看到,函数increx的作用域存在于其局部,但是却在每次调用函数的时候沿用之前的值!这是因为static定义的变量是静态变量,有着静态存储位置(变量存储位置固定不动,若在代码中已经初始化则存在于data段,否则存在于bss段),而不是存在于栈上,因此每次调用函数读取到的变量的值都是静态存储区的值。

    static的意义

    1. 全局静态变量

      • 不会被其它文件所访问和修改
      • 其它文件中可以使用相同名字的变量,不会发生冲突
    2. 局部静态变量

      • 可以用作计数器,每次函数调用的时候可以进行计数
    3. 静态函数

      • 其它文件中可以定义相同名字的函数,不会发生冲突
      • 静态函数不能被其它文件所用
      • 静态函数会被分配在一个一直使用的存储器,直到程序退出,避免了调用函数时进栈出栈,提升运行速度

    参考书目

    1. 《Unix环境高级编程》(中文第三版)
    2. 《C primer plus》(中文第五版)

    参考博客

    C语言存储空间布局以及static详解——奔人之旅

  • 相关阅读:
    关于我的新博客
    我今天申请了blog!
    Win XP / Win 7上配置eclipse+CDT+MinGW,和相关问题的解决办法
    Android app Installation error: INSTALL_FAILED_CONFLICTING_PROVIDER
    用adb安装程序,和在电脑和设备之间传文件
    eclipse 断点调试快捷键(转)
    找不到设备,device not found错误
    eclipse里面的C printf 先输出到缓冲区
    Eclipse Outline 图示
    如何获得Android系统版本
  • 原文地址:https://www.cnblogs.com/yanhewu/p/8360541.html
Copyright © 2011-2022 走看看