C变量的存储方式

变量可以分为全局变量、静态全局变量、静态局部变量和局部变量 


按存储区域分:全局变量、静态全局变量和静态局部变量都存放在内存的全局数据区,局部变量存放在内存的栈区


按作用域分:全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。


全局变量和静态变量如果没有手工初始化,则由编译器初始化为0。局部变量的值不可知。


=================

根据谭浩强的C总结:

作用角度度分:

      局部变量:

                自动变量,即动态局部变量(离开函数,值就消失)

                静态局部变量(离开函数,值保留)

                寄存器变量(离开函数,值就消失)

                (形式参数可以定义为自动变量或寄存器变量)

     全局变量:

                静态外部变量(只限本文件应用)

                  外部变量(即非静态的外部变量,运行其他文件应用)


生存周期划分:

      动态存储:在调用函数时临时分配单元;

      静态存储:程序整个运行时间都存在;


         动态存储:

                自动变量(本函数内有效)

                寄存器变量(本函数内有效)

                形式参数(本函数内有效)

        静态存储:

                静态局部变量(函数内有效)

                静态外部变量(本文件内 有效)

                外部变量(其他文件可以应用)


存放位置划分:

         静态存储区:

                静态局部变量

                静态外部变量(函数外部静态变量)

                外部变量(可以被其他文件引用)

        动态存储区:

               自动变量

                形式参数

                CPU中的寄存器:寄存器变量


==============================

全局变量:变量的存储类型(变量的生存期):是指为变量分配使用内存空间的方式,也称存储方式。

  1. 静态存储:外部变量(所有函数之外的定义的变量为外部变量,属全局变量,使用静态存储方式保存,保存在全局区,即静态区)和静态变量
  2. 动态存储:自动变量(属于局部变量)和寄存器变量(保存在CPU的寄存器,只有局部变量才能定义为寄存器变量,将变量定义为寄存器变量后就不能对期取址,因为寄存器是没有内存地址的)

自动变量(auto)----生存期:定义该变量的函数被调用时才给它分配存储单元,开始它的生存期,函数调用结束,释放存储单元,结束生存期;作用域:定义它的函数或复合语句内。注,系统不会为其进行默认的初使化赋值值。

寄存器变量(register)----寄存器变量是局部变量,使用动态存储方式,只有 局部自动变量和形式参数才可以作为寄存器变量。

外部变量----也称全局变量。具有全局作用域,只需在一个源文件中定义,就可以作用于所有的源文件,当然,其他不包含全局变量定义的源文件需要用extern关键字再次声明这个全局变量。

静态变量 ----静态局部变量:在函数内定义,但当函数退出后,静态局部变量始终还存在,其占用的内存单元不会被人释放,只有当程序结束时,才会随全局变量一起释放。 生存期 :整个源程序(从变量定义开始到程序结束)。 作用域 :定义该变量的函数内。退出该函数后,尽管该变量还存在,但不能使用它。如果再次调用定义它的函数时,它又可继续使用,而且保存了前次被人调用后留下的值;静态全局变量:只能在其所在文件模块中的函数中使用。其他文件模块中的函数将不能访问。

内存区域的划分:

  1. 栈区:由编译器自动分配和释放的内存区域,用于存放函数的参数值,局部变量的值等。随着函数的调用和返回,栈区的数据将动态变化。
  2. 堆区:程序员向系统申请或释放。若程序员在程序结束时还没有释放,则可能由操作系统回收。malloc.
  3. 全局区:用来保存全局变量和静态变量。在进入程序时分配区域,程序结束后由系统释放。
  4. 文字常量区:用于保存常量字符串的内存区域,程序结束后,由系统释放。
  5. 程序代码区:用于保存函数体的二进制代码。







总结: 
1. 对于非静态局部变量 
变量的存放位置为堆栈,初始化的数值存放在代码段中,即.text,非位置相关 
2. 对于静态变量 
变量的存放位置为.bss段,初始化数值也存放在.bss段,若未初始化则自动初始化为0,是位置相关的.

3. 对于局部数组 

a) 未初始化数组:存放在堆栈中 
b) 初始化数组:初始化的数组存放在.rodata段,是位置相关的.

4. 对于全局变量 
存放在.data段中,若未初始化则自动初始化为0, 是位置相关的.




局部变量保存在栈里
栈和堆的区别是
栈是系统根据变量大小自动分配空间的
堆是你用new,malloc等手动分配空间的

局部变量保存在栈内存区;
栈内存区的地址是连续的,由系统控制速度较快而
堆内存区的地址是不连续的,它是系统将空闲内存块链接起来的链表,
用户用new/malloc请求分配时,找到第一个满足大小要求的块从链表中删除此节点,
然后分给用户,没有栈内存速度快,但是很灵活。

操作系统给程序运行的内存非了4个区域:
1 代码区:顾名思义就是存放运行的代码的
2 全局数据区: 存放全局数据和静态数据以及常量.
3 栈区 函数调用时的返回地址,参数压栈,局部变量,返回数据等都存放在栈区.
4 堆区,存放程序动态分配的内存(new,malloc等函数分配的)

栈内存是由系统自己分配和释放的,而堆内存要由程序员自己全全控制的,否则会出现内存泄露.





代码段,只读数据段(常量,字面值,const声明的变量),

已初始化可读写数据段(已初始化静态和全局变量),

未初始化可读写数据段(未初始化静态和全局变量),栈,堆。


看了之后对于const声明的变量有几个疑惑:

1.存储位置:对于一个const类型的局部变量,真的是分配在“只读数据段”?还是和普通局部变量一样在栈上分配内存?
2.声明周期:“只读数据段”,是和静态变量一样程序运行前就分配好内存,程序退出时才释放内存,生命周期是整个程序运行时间?
3.对于一个const类型的局部变量,如const int a=1;1这个值是在编译期间就确定的,还是到运行时才确定的?
4.问题1,3对于const类型的全局变量呢?
查了好多资料,都不太清楚,还有矛盾的地方,求详细解答。。。求高手。。。


回答你问题:
1.局部const,并不是在常量区分配的,编译器会将const优化,类似于宏定义,出现const变量的地方在编译时就已经替换其值了。所以其实根本没有分配丝毫空间。(只有当你取变量的地址时,才会在栈上分配空间,但是这个分配的空间其实没有什么意义的,因为所有取const变量值的地方,编译时就已经替换成初值了)

2.内存是运行时(运行初期)分配的,但分配内存的大小编译时就决定了。“只读数据段”的内存,运行完才释放。

3.const int a=1;其实类似于宏定义#define a 1,编译时就将局部函数内的a替换成了1。

4.对于全局的const变量,是在常量区分配内存的,是真正的常量。




  

  1、首先,讲下 “堆 heap” 和 “栈 stack” 的区别:

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

    (1)、栈区 stack :由编译器自动分配释放,

              存放函数的参数值,局部变量的值等。

              这个栈的操作方式类似于数据结构中的栈。

    (2)、堆区 heap :一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,

              注意它与数据结构中的堆是两回事,分配方式类似于链表。

    (3)、全局区(静态去)static : 全局变量和静态变量的存储是放在一块的。

                    初始化的全局变量和静态变量在一块区域,

                    未初始化的全局变量和静态变量又放在相邻的另一块区域中。

                    程序结束后由系统释放。

    (4)、文字常量区  : 常量字符串放在这里。

               程序结束后由系统释放。

    (5)、程序代码区 : 存放函数体的2进制代码。


  2、例子程序 

    这是一个前辈写的,非常详细 

    //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"优化成一个地方。 

    } 



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值