全局变量与局部变量在内存中的区别详细解析

 更新时间:2013年10月11日 09:59:08   作者:  
以下是对全局变量与局部变量在内存中的区别进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助

一、预备知识—程序的内存分配

一个由c/C++编译的程序占用的内存分为以下几个部分

1、栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域(.data),未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(.bss)。 - 程序结束后由系统释放。

4、文字常量区 —常量字符串就是放在这里的(.rodata)。 程序结束后由系统释放。

5、程序代码区—存放函数体的二进制代码(.text)。

二、例子程序
这是一个前辈写的,非常详细

复制代码 代码如下:

//main.cpp
int a = 0;          // 全局初始化区
char *p1;           // 全局未初始化区
main()
{
  int b;            // 栈区
  char s[] = "abc"; // 栈区
  char *p2;         // 栈区
  char *p3 = "123456";     // "123456/0" 在常量区,p3在栈区
  static int c =0;         // 全局(静态)初始化区

  p1 = (char *)malloc(10);
  p2 = (char *)malloc(20); // 分配得来的10和20字节的区域就在堆区

  strcpy(p1, "123456");    // "123456/0" 放在常量区,编译器可能会将它
                              // 与p3所指向的"123456"优化成一个地方。
}

static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?

答:
1)
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。

2) 从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。                  

3) static函数与普通函数作用域不同,仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件   

综上所述:

static全局变量与普通的全局变量有什么区别:

static全局变量只初使化一次,防止在其他文件单元中被引用;   

static局部变量和普通局部变量有什么区别:

static局部变量只被初始化一次,下一次依据上一次结果值;   

static函数与普通函数有什么区别:

static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

 ==============================================================
一个C语言变量分配的实际例子:
 
我们来看看在可执行文件中,变量们会被分配在哪些区里.这里以可执行文件为例子,可执行文件有固定的内存加载地址,符号(函数/变量的名字)将来在内存里的地址连接器是可以提前确定的。

源程序编译连接的结果是形成1堆汇编指令代码,大致分为.text .data .bss等几个节区(section)。对于.exe文件和.so文件,全局和静态变量都放在.data 或.bss段(gas把源文件从头到尾扫描1遍,才知道一个变量的全部情况:是否定义;类型;是否初始化。然后把初始化的变量在.data段里分配位置和 空间,把没初始化的变量在.bss段里分配位置和空间,没定义的变量分配在.undef段)。汇编指令代码里全局变量表现为一个内存地址(全局变量在目标 文件里是一个偏移值,加载进内存里是一个内存地址)。临时变量在汇编代码里变成ebp/esp+n,表现为一个堆栈地址,化为程序正文(.text)的一 部分。有些变量的最终内存地址在加载进内存之前还不能确定,需要加载进内存才可以计算出来.

全局变量 作用域是跨越多个源程序的。因此全局变量不能重名。静态变量作用域是位于单个源程序内。多个源程序可以有同名的全局静态变量。本例中,为了区分多个同名的静态变量,gcc 用 c444和c444.0 来加以区别。

复制代码 代码如下:

[test@redhat]// more aaa.c
# include <stdio.h>
int a111 = 0;              // 全局变量 已初始化
char *p111 = "654321";     // 全局指针变量 已经初始化
static int c444 = 9;       // 静态全局变量 已经初始化
static int c555;           // 静态全局变量 未初始化
main()
{
    int b222;              // 局部变量
    char s333[] = "abc";   // 局部变量
    char *p222;            // 局部变量
    char *p333 = "123456";    // 局部变量
    static int c444 =0;       // 已初始化静态局部变量,与前面静态全局变量重名
    p111 = (char *)malloc(10);
    p222 = (char *)malloc(20);
    strcpy(p111, "123456");
}

相关文章

  • 一文搞懂C++多态的用法

    一文搞懂C++多态的用法

    C++多态是在继承的基础上实现的,了解多态之前我们需要掌握一定的C++继承的知识,本文将介绍C++中多态的概念,构成条件以及用法,感兴趣的可以学习一下
    2022-04-04
  • 十个C++恶搞朋友的代码合集

    十个C++恶搞朋友的代码合集

    这篇文章主要为大家整理了十个C++中可以恶搞朋友的代码合集(注意!从第五个开始为危险/永久性程序,请慎重使用),感兴趣的小伙伴可以收藏一下
    2023-02-02
  • C++动态规划实现查找最长公共子序列

    C++动态规划实现查找最长公共子序列

    这篇文章主要介绍了C++动态规划最长公共子序列,在动态规划中,你要将某个指标最大化。在这个例子中,你要找出最长公共子序列
    2022-06-06
  • C++类的定义与实现

    C++类的定义与实现

    这篇文章主要介绍了C++类的定义与实现,违章围绕C++类的定义的相关资料展开全文内容,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-01-01
  • java 中ArrayList与LinkedList性能比较

    java 中ArrayList与LinkedList性能比较

    这篇文章主要介绍了java 中ArrayList与LinkedList性能比较的相关资料,需要的朋友可以参考下
    2017-03-03
  • 深入分析Linux下如何对C语言进行编程

    深入分析Linux下如何对C语言进行编程

    本篇文章介绍了,如何在Linux下对C语言进行编程的详细概述。需要的朋友参考下
    2013-05-05
  • C语言实现猜数字小游戏

    C语言实现猜数字小游戏

    这篇文章主要为大家详细介绍了C语言实现猜数字小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • C语言实现查询自动售货机中的商品价格【实例分享】

    C语言实现查询自动售货机中的商品价格【实例分享】

    本文主要介绍了C语言实现查询自动售货机中的商品价格的相关资料。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-04-04
  • C语言 数据存储方式知识点详解

    C语言 数据存储方式知识点详解

    在本篇文章里小编给大家整理的是关于C语言 数据存储方式知识点详解,有需要的朋友们可以学习参考下。
    2020-02-02
  • C++多继承同名隐藏实例详细介绍

    C++多继承同名隐藏实例详细介绍

    多继承可以看作是单继承的扩展。所谓多继承是指派生类具有多个基类,派生类..本文将对C++多继承同名隐藏实例进行分析
    2012-11-11

最新评论