Linux 下C语言学习(四)——变量的类型和程序各部分代码在内存中的位置

变量类型

块变量

   语句块(程序块):指使用大括号{}括起来的一组语句

   在一个语句块内部的变量,叫做块变量

  if(...)

   {

     int i;  //块变量

     ...

  }                                           

  

(1)生命周期:从定义开始,一直到程序块结束

(2)作用域(访问范围): 在语句块内部

 

局部变量

   在函数内部定义的变量叫做局部变量,局部如果没有进行初始化,那么这个变量是一个随机数

  void fn(void)

   {

     int a;

  }     

(1)生命周期:从定义开始,一直到函数结束

(2)作用域:从定义开始之后的整个函数内部可以访问

 

 

静态局部变量      使用关键字static修饰的局部变量

   void fn(void)

    {

      static int a;

   }  

(1)生命周期:整个程序

(2)作用域:和普通局部变量一样 

(3)作用:一般可以用于计数,只要程序不结束,可以实现不停的累加

 

全局变量   (在全局变量前面加static  成为静态全局变量(表示只能在当前文件使用))

定义在整个程序内部的变量,一般都定义在程序的开头位置,或者头文件,全局变量会被自动初始化为0

(1)生命周期:定义开始,一直到整个程序结束

(2)作用域:定义开始,在整个程序内部都可以访问

 

不同范围的同名变量

如果全局变量、局部变量以及块变量同名,那么在块变量范围内,块变量优先,在局部变量范围内,局部变量优先,最后才轮到全局变量 -》 局部优先

 

程序在内存中区域划分:

       操作系统对内存条进行以下分配,它把内存条分为了五个部分:

(1)程序段:用来存放程序的代码,程序段是只读的

   (2)数据段:用来存放的已经初始化的全局变量和静态局部变量

   (3)BSS段:用来存放没有进行初始化的全局变量,自动初始化为0

   (4)堆区:用来进行动态内存的分配(malloc/calloc/realloc/free)

   (5)栈区:操作系统自动进行内存的分配和回收,一般存放局部变量

 

例子:

//使用递归函数实现计算n的阶乘

#include <stdio.h>

 

//定义一个递归函数

Int p = 0;

int jiecheng(int num)

{

    if(1 ==num)

    {

        StaticInt lv = 0;

        return1;

    }

    returnnum*jiecheng(num-1);

}

 

int main()

{

    int data= 0;

    printf("请输入一个整数:\n");

    scanf("%d",&data);

    printf("%d的阶乘是%d\n",data,jiecheng(data));

    return 0;

}

1、  在程序段中,保存了这个的源文件的内容

2、  数据段中,保存了全局变量和静态局部变量的内容(值与名称),即保存了 p= 0 和 lv = 0

3、  BSS 段  ,由于没有没有初始化的全局变量,则这个没有保存

4、堆区,是程序员手动申请内存时,系统分配的区域,释放的时候也是程序员手动释放一般使用(malloc/calloc/realloc/free)

5、栈区,没有使用(malloc/calloc/realloc)申请的内存,操作系统自动进行内存的分配和回收,一般存放局部变量 如上边 data = 0; num

 

详细分析:

       程序第一步,先进行预处理,判断有没有语法的错误,并导入相应头文件中对应的源文件,第二步将代码编译成.o文件,第三步生成可执行文件

在运行可执行文件的时候开始分配内存,

第一:因为在main函数之前得先扫描全局变量,所以先分配的是p 的内存(在数据段中),并赋值为0,但是0是保存在只读常量区,还有字符,字符串都一样,所谓的赋值就是在只读常量区中复制一份数值然后赋予变量

第二:进入main函数了,在栈区分配data的内存,并赋值为0;

第三:调用printf函数,printf函数调用的时候,系统在内存条栈区分配(分配规则系统自定)函数执行所需空间(该大小是函数变量),之后屏幕打印   “请输入一个整数:\n”

第四:调用scanf函数,同上,不过该函数功能则是保存了用户输入的值,在通过&data,找到data地址,把值赋进去

第五:调用自定义函数,由于该函数为递归函数,但是递归过程调用的函数还是该函数,所以地址不变

 

注意:

    register:寄存器

    修饰的变量叫寄存器变量,告诉编译器,这个变量会频繁使用,请保存在寄存器中,因为读取寄存器中数据的速度比内存快

使用限制:

   (1)必须能被CPU的寄存器接受

   (2)不能对寄存器中的变量取地址

   (3)有些系统并不会把这种变量放在寄存器中,主要取决于编译器

(4)还有的编译器会把很频繁使用的变量放在寄存器中,虽然他们没有被register修饰

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值