C语言中局部变量和全局变量在内存中的存放位置

2023-11-13

 

C语言中局部变量和全局变量变量的存储类别(static,extern,auto,register)

 

1.局部变量和全局变量

在讨论函数的形参变量时曾经提到,形参变量只在被调用期间才分配内存单元,调用结束立即释放。这一点表明形参变量只有在函数内才是有效的,离开该函数就不能再使用了。这种变量有效性的范围称变量的作用域。不仅对于形参变量,C语言中所有的量都有自己的作用域。变量说明的方式不同,其作用域也不同。C语言中的变量,按作用域范围可分为两种,即局部变量和全局变量。

1.1局部变量

   局部变量也称为内部变量。局部变量是在函数内作定义说明的。其作用域仅限于函数内,离开该函数后再使用这种变量是非法的。

【例1.1

    int f1(int a)        /*函数f1*/

    {

        int b,c;     

    }

a,b,c有效

    int f2(int x)        /*函数f2*/

    {

          int y,z;

   }

x,y,z有效

    int main(void)

    {

         int m,n;

    }

m,n有效

    在函数f1内定义了三个变量,a为形参,b,c为一般变量。在 f1的范围内a,b,c有效,或者说a,b,c变量的作用域限于f1内。同理,x,y,z的作用域限于f2内。m,n的作用域限于main函数内。关于局部变量的作用域还要说明以下几点:

     1)主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用。同时,主函数中也不能使用其它函数中定义的变量。因为主函数也是一个函数,它与其它函数是平行关系。这一点是与其它语言不同的,应予以注意。

     2)形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量

     3)允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。如在前例中,形参和实参的变量名都为n,是完全允许的。

     4)在复合语句中也可定义变量,其作用域只在复合语句范围内。

【例1.2

int main(void)

{

       int s,a;

      {

              int b;

              s=a+b;

             /*b作用域*/

       }

/*s,a作用域*/

}

【例1.3

int main(void)

{

    int i=2,j=3,k;

    k=i+j;

    {

       int k=8;

       printf("%d\n",k);

    }

    printf("%d\n",k);

}

     本程序在main中定义了i,j,k三个变量,其中k未赋初值。而在复合语句内又定义了一个变量k,并赋初值为8。应该注意这两个k不是同一个变量。在复合语句外由main定义的k起作用,而在复合语句内则由在复合语句内定义的k起作用。因此程序第4行的kmain所定义,其值应为5。第7行输出k值,该行在复合语句内,由复合语句内定义的k起作用,其初值为8,故输出值为8,第9行输出ik值。i是在整个程序中有效的,第7行对i赋值为3,故以输出也为3。而第9行已在复合语句之外,输出的k应为main所定义的k,此k值由第4行已获得为5,故输出也为5

 

1.2全局变量

全局变量也称为外部变量,它是在函数外部定义的变量。它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序。在函数中使用全局变量,一般应作全局变量说明。只有在函数内经过说明的全局变量才能使用。全局变量的说明符为extern。但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。

【例1.4

   int a,b;          /*外部变量*/

    void f1()         /*函数f1*/

    {

      ……

    }

   float x,y;         /*外部变量*/

    int fz()          /*函数fz*/

    {

      ……

    }

    Int main(void)           /*主函数*/

    {

      ……

    }

    从上例可以看出abxy都是在函数外部定义的外部变量,都是全局变量。但x,y定义在函数f1之后,而在f1内又无对x,y的说明,所以它们在f1内无效。a,b定义在源程序最前面,因此在f1,f2main内不加说明也可使用。

【例1.5】输入正方体的长宽高l,w,h。求体积及三个面x*y,x*z,y*z的面积。

int s1,s2,s3;

int vs( int a,int b,int c)

{

    int v;

    v=a*b*c;

    s1=a*b;

    s2=b*c;

    s3=a*c;

    return v;

}

int main(void)

{

    int v,l,w,h;

    printf("\ninput length,width and height\n");

    scanf("%d%d%d",&l,&w,&h);

    v=vs(l,w,h);

    printf("\nv=%d,s1=%d,s2=%d,s3=%d\n",v,s1,s2,s3);

}

【例1.6外部变量与局部变量同名

int a=3,b=5;     /*a,b为外部变量*/

max(int a,int b) /*a,b为外部变量*/

{

    int c;

    c=a>b?a:b;

    return(c);

}

 int main(void)  

{

    int a=8;

    printf("%d\n",max(a,b));

}

    如果同一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量被屏蔽,即它不起作用。

 

2.变量的存储类别

2.1动态存储方式与静态动态存储方式

    前面已经介绍了,从变量的作用域(即从空间)角度来分,可以分为全局变量局部变量

    从另一个角度,从变量值存在的作时间(即生存期)角度来分,可以分为静态存储方式动态存储方式

    静态存储方式:是指在程序运行期间分配固定的存储空间的方式。

    动态存储方式:是在程序运行期间根据需要进行动态的分配存储空间的方式。

    用户存储空间可以分为三个部分:

        1)程序区;

         2)静态存储区;

        3)动态存储区

    全局变量全部存放在静态存储区,在程序开始执行时给全局变量分配存储区,程序行完毕就释放。在程序执行过程中它们占据固定的存储单元,而不动态地进行分配和释放;

    动态存储区存放以下数据:

        1)函数形式参数;

        2)自动变量(未加static声明的局部变量);

        3) 函数调用实的现场保护和返回地址;

    对以上这些数据,在函数开始调用时分配动态存储空间,函数结束时释放这些空间。

    在c语言中,每个变量和函数有两个属性:数据类型和数据的存储类别。

 

2.2auto变量

函数中的局部变量,如不专门声明为static存储类别,都是动态地分配存储空间的,数据存储在动态存储区中。函数中的形参和在函数中定义的变量(包括在复合语句中定义的变量),都属此类,在调用该函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空间。这类局部变量称为自动变量。自动变量用关键字auto作存储类别的声明。

【例1.7

int f(int a)         /*定义f函数,a为参数*/

{

    auto int b,c=3;     /*定义b,c自动变量*/

}

a是形参,b,c是自动变量,对c赋初值3。执行完f函数后,自动释放a,b,c所占的存储单元。

关键字auto可以省略,auto不写则隐含定为“自动存储类别”,属于动态存储方式。

 

2.3static声明局部变量

有时希望函数中的局部变量的值在函数调用结束后不消失而保留原值,这时就应该指定局部变量为“静态局部变量”,用关键字static进行声明。

【例1.8考察静态局部变量的值。

f(int a)

{

    auto b=0;

    static c=3;

    b=b+1;

    c=c+1;

    return(a+b+c);

}

int main(void)

{

    int a=2,i;

    for(i=0;i<3;i++)

         printf("%d",f(a));

}

对静态局部变量的说明:

   1)静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储空间,函数调用结束后即释放。

    2)静态局部变量在编译时赋初值,即只赋初值一次;而对自动变量赋初值是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。

    3)如果在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符变量)。而对自动变量来说,如果不赋初值则它的值是一个不确定的值。

【例1.9】打印15的阶乘值。

int fac(int n)

{

    static int f=1;

    f=f*n;

    return(f);

}

int main(void)

{

    int i;

    for(i=1;i<=5;i++)

        printf("%d!=%d\n",i,fac(i));

}

 

2.4register变量

    为了提高效率,C语言允许将局部变量得值放在CPU中的寄存器中,这种变量叫寄存器变量,用关键字register作声明。

【例2.0使用寄存器变量。

int fac(int n)

{

    register int i,f=1;

    for(i=1;i<=n;i++)

        f=f*I;

     return(f);

}

int main(void)

{

    int i;

    for(i=0;i<=5;i++)

        printf("%d!=%d\n",i,fac(i));

}

说明:

    1) 只有局部自动变量和形式参数可以作为寄存器变量;

    2)一个计算机系统中的寄存器数目有限,不能定义任意多个寄存器变量;

    3)局部静态变量不能定义为寄存器变量。

 

2.5用extern声明外部变量

外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量。

【例2.1extern声明外部变量,扩展程序文件中的作用域。

int max(int x,int y)

{

    int z;

    z=x>y?x:y;

    return(z);

}

int main(void)

{

    extern A,B;

    printf("%d\n",max(A,B));

}

int A=13,B=-8;

    说明:在本程序文件的最后1行定义了外部变量A,B,但由于外部变量定义的位置在函数main之后,因此本来在main函数中不能引用外部变量A,B。现在我们在main函数中用extern对A和B进行“外部变量声明”,就可以从“声明”处起,合法地使用该外部变量A和B。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言中局部变量和全局变量在内存中的存放位置 的相关文章

  • C语言中,变量的按作用域角度分类的几种情况

    c语言中 变量按作用域角度分 分为局部变量和全局变量 1 局部变量是在一个函数内部或一个代码块中定义的变量 只能在被函数和代码块范围内有效 如 void test int b 20 b是一个局部变量 在test函数内有效 int main
  • 延时函数中用全局变量还是用局部变量

    从不上系统角度 如果中断函数中没有调用延时函数 就都可以 但是如果中断函数中有用到延时函数 就用 局部变量 因此 全部使用局部变量最好
  • postman实战:2.参数化csv和json

    在上节课讲解了使用postman做接口测试时 如何设置环境变量和全局变量关联参数 关联环境变量和全局变量中参数时 他们的作用范围再来回顾一下 下面来看一下postman里面关于参数化的应用 首先分析下应用场景 1 某一个接口我们对入参设计了
  • linux echo

    linux echo功能说明 显示文字 语 法 echo ne 字符串 或 echo help version 补充说明 echo会将输入的字符串送往标准输出 输出的字符串间以空白字符隔开 并在最后加上换行号 参 数 n 不要在最后自动换行
  • 全局/静态变量初始化为0出错? 全局/静态变量初始化为0放在bss段还是data段?

    1 有初始化的全局变量 该全局变量存放在data段 2 没有初始值的全局变量放在BSS段 实际上在arm linux gcc这个开发环境中 如果全局变量的初始值是0 编译器会将该全局变量放在BSS段 初始值是0的全局变量放在BSS段会有什么
  • 补遗篇之命名空间污染

    概念 C标准规定 除非用static限定 否则全局变量与函数都作用于全局 见补遗篇static 也就是说一个模块中定义的函数与全局变量可在所有其他模块中被调用 这导致C的符号命名没有层次 不同模块间名字相互冲突的概率很高 学术的表述就是 C
  • 学习使用vs2019编写一个Linux c++程序

    前言 前些日子 在centos捣鼓C 程序 6 5版本的GCC4 4实在太旧了 不支持C 11 官方说得升级到GCC4 7以上 于是乎 尝试更新GCC 一顿操作猛如虎 一看战绩0 5 不成功 便成仁 一气之下 整了个Centos8 2 这下
  • Java中局部变量、静态变量、静态方法的有效范围与调用

    1 局部变量 定义 在成员方法中定义的变量称为局部变量 方法中的形参也可以作为局部变量 例 public void method1 n i均为局部变量 int n for int i 0 i lt 5 i System out printl
  • 关于javascript中的函数作用域

    var scope global function f alert log scope 输出 undefined 而不是 global var scope local 变量在这里赋初值 单变量本身在函数体内任何地方军事有定义的 consol
  • vue中使用.env文件配置全局变量

    首先根目录下创建 env或者 env production文件 生产环境 env develpment文件 开发环境 变量命名格式 键值对形式 VUE APP NAME value VUE APP 是规定的命名格式 NAME是自定义的变量名
  • ThreadLocal与局部变量

    ThreadLocal和线程局部变量有什么区别 我们先看一段代码 如下 public class ThreadLocalLearn static ThreadLocal
  • stm32局部变量过大,导致栈溢出

    在做一个以stm32为主控的项目时发现自己程序中一个机构体里面的数据总是一运行就被改变 刚开始以为是自己不小心在哪个地方用了extern扩展了变量的作用域 重新赋了值 自己忘记了 后来查找了好久都没有其他地方使用这个结构体变量 于是开始单步
  • 关键字static、Const、Volatile的作用是什么

    关键字static的作用是什么 在C语言中 关键字static有三个明显的作用 1 在函数体 一个被声明为静态的变量在这一函数被调用结束后不释放其存储空间 定义为static的局部变量的存储在全局区 静态区 而一般的局部变量存储在栈中 2
  • java变量的类别和作用范围

    1 类别及作用范围 类变量 在类中用static修饰的字段 存储位置 方法区 生命周期 随着JVM的消亡而消失 生命周期最长 局部变量 在方法中存在的 或者形参 存储位置 栈帧中 生命周期 随着方法的调用而存在 生命周期最短 实例变量 在类
  • C/C++ --- 全局变量初始化总结

    注意 本文所说的全局变量指的是 variables with static storage 措词来自 c 的语言标准文档 什么时候初始化 根据 C 标准 全局变量的初始化要在 main 函数执行前完成 常识无疑 但是这个说法有点含糊 mai
  • C语言中局部变量和全局变量在内存中的存放位置

    C语言中局部变量和全局变量变量的存储类别 static extern auto register 1 局部变量和全局变量 在讨论函数的形参变量时曾经提到 形参变量只在被调用期间才分配内存单元 调用结束立即释放 这一点表明形参变量只有在函数内
  • SO_RCVTIMEO超时errno

    首先打印一次recv调用失败的errno值和各个宏的值 由上可知 EAGIN和EWOULDBLOCK的值都是11 其实EAGIN是在setsockopt设置SO RCVTIMEO或SO SNDTIMEO后 recv或者send系列函数超时等
  • Java的作用域

    Java的作用域 作用域是指变量能生效的区域范围 声明在不同地方的变量具有不同的作用域 而决定作用域的就是花括号的位置 同时还决定了变量名的可见性与生命周期 Java语言中 变量的类型主要有成员变量 静态变量 和局部变量三种 类的成员变量
  • java中的八种数据类型、变量与常量

    内存空间所占字节数 8位等于1字节 数值型 1 整数类型 byte 1 short 2 int 4 long 8 2 浮点类型 float 4 double 8 字符型 char 2 布尔型 boolean 1或4 取值范围 byte 12
  • 彻底理解js中的闭包

    闭包是js的一个难点也是它的一个特色 是我们必须掌握的js高级特性 那么什么是闭包呢 它又有什么用呢 我们都知道 js的作用域分两种 全局和局部 基于我们所熟悉的作用域链相关知识 我们知道在js作用域环境中访问变量的权利是由内向外的 内部作

随机推荐

  • Python3基础入门

    文章目录 前言 基础说明 Python安装 Windows Ubuntu 开发环境 程序编写 模块和包 模块 module 包 package pip和换源 总结 前言 Python是目前非常流行的编程语言 这篇文章将对其相关入门内容进行说
  • JS判断数据类型的5种方法

    我们先来了解一下JS中数据类型有哪些 基本数据类型 值类型 String Number boolean null undefined symbol es6新增的 引用数据类型 引用类型 object 包含 Function Array Da
  • CSS line-height概念与举例

    本文同时发表在https github com zhangyachen zhangyachen github io issues 37 定义 两行文字基线之间的距离 基线的大体位置 基线的位置可以看成x字母下边缘的位置 不同字体的基线位置会
  • 微信公众号H5音频视频自动播放(安卓,苹果)

    我们都知道音频视频的自动播放被浏览器或者微信给限制了 必须用户跟页面交互才可以播放音视频 解决办法就是引入微信的jssdk 然后监听 WeixinJSBridgeReady 来实现自动播放 引入jssdk 音频或视频自动播放 documen
  • 查看运行的java程序的几种方式

    windows 任务管理器可以查看进程和线程数 也可以用来杀死进程 tasklist 查看进程 tasklist 杀死进程 linux ps ef 查看所有进程 ps ft p 查看某个进程 PID 的所有线程 kill 杀死进程 top
  • 【转载】手把手教你用 “三步法” 快速实现 4K+ 超高分辨率满细节出图

    手把手教你用 三步法 快速实现 4K 超高分辨率满细节出图 https ngabbs com read php tid 35888357 rand 488 准备工作 如果你的显存不足以直出你期望的最终分辨率 请先按照你习惯的方式安装 切片扩
  • uniapp - Map地图组件属性示例

    目录 1 markers 点标记 用于在地图上显示标记的位置 2 点聚合 3 polygons 4 include points 可以实现自动缩放展示视图内所有的点标记 5 polyline 线 map uni app官网 1 marker
  • littleVGL学习笔记5——lv_obj 基础对象

    1 介绍 littleVGL 是以对象为概念的 而其最核心的基础对象是 lv obj 控件 其他的所有专用控件 比如按钮 标签 列表等 都是在此 lv obj 对象的基础上衍生出来的 所有的控件对象都具有一些共同的属性 如下所示 位置 Po
  • JUC 十二. ReentrantReadWriteLock 与 StampedLock

    目录 一 基础 二 ReentrantReadWriteLock 的锁降级 三 StampedLock 邮戳票据锁 一 基础 ReentrantReadWriteLock 可以看为读读共享 读写 写写依然互斥 总结一句话 读写互斥 读读共享
  • 数字化时代-26:不要做数字空间的难民

    网络是人们新的生存空间 年轻人出生后就存在的空间 与人类社会原先的现实空间并存的人与人交流的空间 在这个空间中 没有自己位置的人 将成为未来社会的难民 年轻人 特别是毕业后的年轻人 需要思考 个人在数字空间中的落脚点和位置 数字原住民 在数
  • Ubuntu 20.04-NVIDIA显卡驱动-安装和卸载-解决黑屏问题

    这一步很重要 202300704更新 黑屏问题主要由linux内核更新导致 一定要保持当前的内核 也就是安装 NVIDIA 驱动时用的内核 sudo apt mark hold linux image generic linux heade
  • Cuda矩阵运算库cuBLAS介绍

    文章目录 简介 cuBLAS库新特性 cuBLAS代码热身 cublasSetMatrix cudaMalloc cublasSscal 源代码 cuBLAS 辅助函数 上下文管理 复制矩阵 数据类型标示 cuBLAS 运算函数 矩阵相乘
  • 有趣的 Async hooks 模块

    在 Node js 中 Async hooks 是一个非常有意思且强大的模块 虽然性能上存在一些问题 在 APM 中 我们可以借助这个模块做很多事情 本文介绍两个有趣的用法 AsyncLocalStorage 在 Node js 中 上下文
  • PaddlePaddle Hackathon 飞桨黑客马拉松热身赛上线!

    挑战自我 拓展技能 激发创新 挑战极限 再次相遇黑客松 我们期待你的加入 第五期 PaddlePaddle Hackathon 飞桨黑客马拉松热身赛上线 本次活动是面向全球开发者的深度学习领域编程活动 鼓励开发者了解和参与飞桨深度学习开源项
  • 如何制作一个简单的网页

    先创建一个文本文档 将后缀名改为 html 然后右击这个 选择打开方式 用记事本打开 开头与结尾要用来写 后一个要加 头部用head 中间部分用body 背景颜色用bgcolor 填一种颜色 字体颜色用text 填一种颜色 切记用英文 你如
  • ubuntu16.04 安装交叉编译工具aarch64-linux-gnu-gcc/g++

    前言 最近需要把人脸识别代码放到RK3399Pro的嵌入式板子上 所以编写好的c 代码要放到板子上编译 或者在ubuntu系统上使用交叉编译工具 编译好可执行文件在放到板子里运行 为了在能在ubuntu系统上能交叉编译 安装aarch64
  • 复杂场景下智能汽车目标检测心得体会

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 引言 一 复杂背景目标检测的复杂是什么 二 目标检测环境的复杂性包含哪些 三 复杂场景目标检测的目标复杂性包含哪些 四 复杂场景目标检测的算法复杂性包含什么 五 总
  • 微信小程序使用face++实现人脸识别登录注册

    Face 是一个 人工智能开放平台 要使用它我们得先注册并进入控制台创建API Key 这是前提 平台网址 https www faceplusplus com cn 整个项目代码我已经上传到网盘 链接 https pan baidu co
  • 高频面试题:服务器CPU占用过高怎么办?搞定只需简单7步

    一 前言 在Java开发岗位的面试中 时不时会出现一些运维类的题目 其实这也反映了后端面试的一种趋势 现在企业对后端开发的要求越来越全面 不仅要求我们会写代码 还要我们能够进行部署和运维 今天九哥就结合一个真实的项目案例 来给大家讲解一道关
  • C语言中局部变量和全局变量在内存中的存放位置

    C语言中局部变量和全局变量变量的存储类别 static extern auto register 1 局部变量和全局变量 在讨论函数的形参变量时曾经提到 形参变量只在被调用期间才分配内存单元 调用结束立即释放 这一点表明形参变量只有在函数内