嵌入式---c语言变量范围及生命周期和定义声明

2023-11-15

嵌入式—c语言变量范围及生命周期

1.局部变量和全局变量

变量分为局部变量和全局变量,因为有的变量只能在本程序中使用,而有的变量可以在其他函数中使用,这就是变量作用域问题。

1.1局部变量

定义:
只能在一定范围内使用的变量称为局部变量
例如:
只能在本函数中才能引用,其他函数是不能使用这些变量的;复合语句中定义的变量只能在该范围内使用,其余是不能使用的。

3种情况

(1)在函数的开头定义

(2)在函数内的复合语句内定义

(3)在函数的外部定义

例如:

//形式参数也是局部变量,变量a只在f1中有效,其他函数可以调用f1函数
//但不能直接引用f1函数的形参a
float f1(int a)
{
    int b,c;
    ...
}
//不同函数可以使用相同的变量名,它们代表不同的对象,互不干扰;
//它们在内存中占不同的单元,不会混淆
char f2(int x,int y)
{
    int b,c;
    ...
}
//主函数定义的m,n两个变量只能在主函数中有效
//主函数中也不能使用其他函数中定义的变量
int main()
{
    int m,n;
    ....
    {
        int c;//只在此复合语句中有效,离开复合语句就无效,系统会把它占用的内存单元释放
        c = a+b;
    }
    ....
        return 0;
}

1.2全局变量

定义:
在函数之外定义的变量称为外部变量,外部变量也称为是全局变量也称为是全称变量。
范围:
从定义变量的位置开始到本源文件结束
作用:
是增加函数键数据联系的渠道,由于同一文件中所有函数都能引用全局变量的值,因此如果在一个函数中改了全局变量的值,就会影响到其他函数中全局变量的值,相当于各个函数间有直接的传递通道。
由于函数的调用只能带回一个函数返回值,因此有时候可以利用全局变量来增加函数间的联系渠道,通过函数调用能得到一个以上的值。
注意:
一般在定义全局变量名的时候,通常第一个字母用大写表示

例如:定义全局变量
float Max = 0;Min = 0 
//有一个一维数组,内放10个学生成绩,写一个函数,当主函数调用此函数后能求出平均分,最高分和最低分 
#include<stdio.h>
float Max = 0;Min = 0;//定义全局变量
float average(float array[],int n);//函数的声明
int main()
{
    float ave,score[10];//定义变量和数组
    int i;
    printf("please enter 10 score:\n");
    for(i=0;i<10;i++)
    {
        scanf("%d",&score[i]);
    }
    //调用函数时,把实参数组score的首元素地址和整数10传递给了形参数组array和形参变量n;
    //函数average的值是return语句带回的aver的值
    ave=average(score,10);
    printf("max=%6.2f\nmin=%6.2f\naverage=%6.2f\n",max,min,ave);
    return 0;
}
float average(float array[],int n)//定义形参,有一个形参是数组
{
    int i;
    float aver,sum=array[0];
     Max=Min=array[0];
    for(i=1;i<n;i++)
    {
        if(array[i]>Max)
            Max=array[i];
        else if(array[i]<Min)
            Min=array[i];
        sum=sum+array[i];
    }
    aver=sum/n;
    return aver;
}
在不必要时不要使用全局变量
①全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要是才开辟单元。        
②它使用函数的通用性降低了,因为如果在函数中引用了全局变量,那么执行情况会受到有关的外部变量的影响,如果将一个函数移到另外一个文件中,还要考虑把有关的外部变量与其他文件的变量同名时,就会出现问题,这样就降低了程序的可靠性和通用性
③使用全局变量过多,会降低程序的清晰性,很难清楚判断出每个瞬时各个外部变量的值。
如果全局变量与局部变量同名,会有什么结果呢?
#include<stdio.h>
int a=3,b=5;//全局变量
int max(int a,int b);//函数的声明
int main()
{
    int a=8;//局部变量a
    printf("max=%d\n",max(a,b));//使用局部变量a和全局变量b
    return 0}
int max(int a,int b)//a,b是形参
{
    int c;
    c=a>b?a:b;
    return c;
}

2.动态存储和静态存储

静态存储:是指在程序运行期间由系统分配固定的存储空间的方式
动态存储:在程序运行期间根据需要进行动态的分配存储空间的方式

2.1存储空间

(1)程序区

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

(3)动态存储区

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

①函数形式参数,在调用函数时给形参分配存储空间

②函数中定义的没有关键字static声明的变量,即自动变量

③函数调用时的现场保护和返回地址等

这些数据在函数调用开始时分配动态存储空间,函数结束时释放这些空间,在程序执行过程中,这种分配和释放是动态的,如果在一个程序中两次调用同一函数,而在此函数中定义了局部变量,在两次调用时分配给这些局部变量的存储空间的地址可能是不相同的。

3.局部变量的存储类型

变量和函数都有两个属性,数据类型(整型,浮点型)和数据的存储类别(静态存储和动态存储)。

存储类别有4种

自动的auto
静态的statis
寄存器register
外部的extern

3.1自动变量(auto)

如果变量没有声明为statis存储类型,都是动态地分配存储空间,数据存储在动态存储区中。例如:局部变量,形参。
定义:在调用函数时,系统会给变量自动分配存储空间,在函数调用结束时就自动释放这些存储空间,这类局部变量称为是自动变量。
程序中大多数的变量属于自动变量,auto可以省略不写。
int f(int a)//定义一个f的函数,a为形参
{
	auto int b,c;//定义b,c为自动变量
	//等价于int b,c;
}

3.2静态局部变量(static局部变量)

定义:
在函数调用结束后局部变量的值不消失而继续保持原来的值,即占用的存储单元不释放,在下一次调用该函数时,该变量的值是上一次函数调用结束的值,用static关键字进行声明。
#include<stdio.h>
int f(int);//函数的声明
int main()
{
    int a=2,i;//自动局部变量
    for(i=0;i<3;i++)
        printf("%d\n",f(a));//输出f(a)的值
    return 0;  
}
int f(int a)
{
    auto int b=0;//自动局部变量
    static c=3;//静态局部变量
    b=b+1;
    c=c+1;
    return a+b+c;
}
分析:
 	第一次:a=2;b=0;c=3;b=b+1=1;c=c+1=4;a+b+c=7;
因为c是一个静态局部变量,并不会立即释放值。
    所以在第二次调用该函数的时候,
    第二次:b=0;c=4(上一次调用的值)

3.3静态变量和自动变量的区别

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

(2)如果对静态局部变量赋初值,以后每次都用该函数时不会在重新赋初值而是保留上次函数调用结束的值;自动变量赋初值,每次调用函数后都会重新赋初值。

(3)如果没有对静态局部变量赋初值,编译会自动赋上0或’\0’;自动变量不赋初值便是一个不确定的值,因为每次函数调用结束后存储单元已经释放,下一次调用又会重新分配存储单元,而存储单元中的内容是不可知的。

(4)静态局部变量在函数调用结束后任然可以存在,其他函数不能引用它。

(5)静态存储降低了程序的可读性

//输出1到5的阶乘
#include<stdio.h>
int fac(int);
int main()
{
    int n;
    for(n=1;n<=5;n++)
    {
        printf("d!=%d\n",n,fac(n));
    }
    return 0;
}
int fac(int n)
{
    static int f = 1;	//保留上次调用结束时的值
    f = f*n;
    return f;
}

3.4寄存器变量(register变量)

定义:将局部变量的值存放在CPU中的寄存器中,需要用时直接从寄存器中取出参加运算,而不必再到内存中去存取。对寄存器的存取速度远远高于对内存的存取速度,可以提高执行效率。
例如:
register int f;//f为寄存器变量

3.5注意

自动变量存储在动态存储区

静态局部变量存储在静态存储区

寄存器存储在CPU中的寄存器中

4.作用域

一般来说,外部变量是在函数的外部定义的全局变量,它的作用域是从变量的定义处开始到本程序文件的末尾,在此作用域内,全局变量可以为程序中各个函数所引用。

扩展外部变量的作用域有以下三种情况

4.1extern 作用一

外部变量不在文件的开头定义,有效作用范围只限于定义到文件结束。在定义之前的函数就不能引用该外部变量。如果需要使用该变量,需要在变量之前加关键字"extern".

表示把外部变量的作用域扩展到此位置

例如:调用函数,求3个整数中的大者。

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

#include<stdio.h>
int max;
int main()
{
	extern int A,B,C;//外部变量的作用域从此处开始
    //等同于int A,B,C;因为她不是定义变量,也可以不指定类型只需要写出外部局部变量名即可。
    printf("Please enter three integer numbers:");
    scanf("%d%d%d",&A,&B,&C);
    printf("max is %d\n",max());
}
int A,B,C;
//定义外部变量ABC,放在了main之后,本来在main函数中是不能引用外部变量ABC,
//但是main函数中对ABC三个变量使用了extern,把ABC的作用域进行了扩展
//否则编译的时候会出错,系统无法得知ABC是后来定义的外部变量
//由于ABC是外部变量,所以在调用max函数的时候不用参数传递,在函数中使用外部变量ABC的值
int max()
{
    int m;
    m = A>B?A:B;
    if(C > m) m = C;
    return m;
}

4.2extern作用二

如果一个程序由多个源文件组成,同时都需要用到一个外部变量x,不能分别在各自文件中定义一个外部变量x,否则在程序连接时会出现“重复定义”错误。

正确做法:一个文件定义局部变量x,另一个文件中用extern对x变量进行声明,编译的时候就可以把x的作用域扩展到本文件中。如果有多个文件都需要使用该变量,都需要加上extern

例:给定b的值,输入a和m,求a*b和a^m的值。

file1文件中包含主函数,file2中用extern声明外部变量,把变量的作用域扩展搭配file2文件。

//file1.c
#include<stdio.h>
int A;//定义外部变量
int power(int);
int main()
{
    int b=3,c,d,m;
    printf("enter the number a and its power m:\n");
    scanf("%d,%d",&A,&m);
    c=A*b;
    printf("%d*%d=%d\n",A,B,C);
    d = power(m);
    printf("%d ** %d=%d\n",A,m,d);//**表示幂次
    return 0;
}
//file2.c
extern A;
//声明在本文件中是一个在“其他文件中定义过的外部变量”
//A的作用域从file1.c扩展到file2.c
int power(int n)
{
    int i,y=1;
    for(i=1;i<=m;i++)
        y*=A;
    return y;
}

4.3static外部变量作用域限制在本文件中

如果已经确认其他文件不需要引用本文件的外部变量,就可以对本文件中的外部变量加上static,成为静态外部变量,以免被其他文件误用,相当于把本文件的外部变量对外界“屏蔽”起来。

static声明变量的作用:

(1)对局部变量用static声明,把它分配到静态存储区域,该变量在整个程序执行期间不释放,其所分配的空间始终存在。

(2)对全局变量用static声明,则该变量的作用域只限制于本文模块(即被声明的文件中)

例如:

//file1.c
static int A;
int main()
{
    .....
}
//file2.c
extern A;
void fun(int n)
{
    A = A*n;//出错
}

注意:

(1)声明局部变量的存储类型和声明全局变量的存储类别的含义是不同的。

(2)对于局部变量来说,声明存储类型的作用是指定变量存储的区域(静态存储区或动态存储区)以及产生的生存期的问题。

(3)对于全局变量来说,由于都是在编译时分配内存的,都存放在静态存储区,声明存储类型的作用**是变量作用域的扩展问题。**

5.存储类别的小结

数据的定义分为(1)数据类型(2)存储类别

static int a;//静态局部整型变量或静态外部整型变量
auto char c;//自动变量,在函数内定义
register int d;//寄存器变量,在函数内定义
extern b;//将已经定义的外部变量b的作用域扩展

(1)作用域角度,有全局变量和局部变量

作用域角度 (空间角度)

(1)全局变量:①静态外部变量(只限于本文本使用static)②外部变量extern(即非静态的外部变量,允许其他文件引用)

(2)局部变量 :①自动变量auto,即动态局部变量(离开函数,值就消失)②静态局部变量static(离开函数,值仍保留)③寄存器变量(离开函数,值就消失)④(形式参数可以自定义为自动变量或寄存器变量)

(2)从变量的生存周期来区分(时间角度)

变量的生存周期分:

(1)动态存储:①自动变量(本函数内有效)②寄存器变量(本函数内有效)③形式参数(本函数内有效)

(2)静态存储:①静态局部变量(函数内有效)②静态外部变量(本文件内有效)③外部变量(用extern声明后,其他文件可引用)

(3)变量值存放的位置

变量值存放的位置

(1)内存中静态存储区:①:静态局部变量②静态外部变量(函数外部静态变量)③外部变量(可为其他文件引用)

(2)内存中动态存储区:自动变量和形式参数

(3)CPU中寄存器:寄存器变量

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

嵌入式---c语言变量范围及生命周期和定义声明 的相关文章

  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 通过 CMIS (dotCMIS) 连接到 SP2010:异常未经授权

    我正在使用 dotCMIS 并且想要简单连接到我的 SP2010 服务器 我尝试用 C 来做到这一点 如下所示http chemistry apache org dotnet getting started with dotcmis htm
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags

随机推荐

  • JAVA简单聊天室的实现

    鉴于之前有不少同学在跟我要客户端的代码 我近期整理了一下 把整个工程都传到github上了 地址 https github co Alexlingl Chatroom 里面有比较详细的工程运行教程 这篇博客则主要对工程的代码实现进行介绍 没
  • 2013中国平板电脑芯片市场分析

    转自 http www wumii com item hpDJVhh5
  • 【问题解决】docker login报错 org.freedesktop.Secret.Error.IsLocked: Cannot create an item in a locked collec...

    问题场景 环境 docker 24 0 2 社区版 Ubuntu Server 18 04LTS 刚刚执行 docker login 登录仓库报错 hellxz bigdata dockerTest docker login harbor
  • 明察秋毫 oracle awr,【学习笔记】Oracle AWR 通过sql语句获取awr/statspack逻辑读/物理读...

    天萃荷净 在日常的性能监控中 我们经常需要需要通过一段时间内数据库的逻辑读 物理读来大致反映数据库的性能情况 这里列出通过awr和statspack来获取相关数据 查询最近30天数据 除掉第一条和最后一条数据 1 Oracle awr逻辑读
  • oracle中show user和select user from dual区别

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 出于好奇 去oracle中尝试了一下这两个语句 1 首先执行show user 直接在sql窗口中执行发现 提示无效的sql语句 这个时候我还没有意识到问题出在哪里 2 然
  • (故障集)——新安装的Ubuntu系统重启后ens33没了

    文章目录 故障集 新安装的Ubuntu系统重启后ens33没了 故障现象 方法一 永久配置 方法二 临时配置 故障集 新安装的Ubuntu系统重启后ens33没了 故障现象 方法一 永久配置 从网上看到使用ifconfig a可以显示lo和
  • SpringBoot事务管理-5个面试核心类源码刨析

    简单的事重复做 你就是专家 重复的事用心做 你就是赢家 在开始讲解SpringBoot事务之前 我们先来整体回顾下事务的概念及特性 便于我们了解SpringBoot是如何解决事务相关问题的 另外这部分也是面试必考内容 需要学习交流的可入群
  • 白翔团队新作:借助CLIP完成场景文字检测

    作者 秃头小苏 编辑 3D视觉开发者社区 原文链接 https arxiv org pdf 2302 14338 pdf 代码链接 https github com wenwenyu TCM 引 言 场景文字检测 Scene text de
  • react使用styled-components

    本文目录 一 styled components 1 1 安装使用 1 2 基于props做样式判断 1 3 样式化任意组件 1 4 动画 一 styled components 1 1 安装使用 styled components它是通过
  • (动手学习深度学习)第4章 房价预测(实战kaggle比赛)

    赛前分析 kaggle竞赛地址 california house prices 数据分析 竞赛大佬方法 它们都是使用集成学习的方法 来集成学习多个模型 第二名和第七名 autogluon 第三名 h2o 第四名 随机森林 代码实现 导入相关
  • c语言文件压缩怎么求压缩比,文件压缩C语言程序设计报告.doc

    文件压缩C语言程序设计报告 课程设计目的 1 巩固和加深学生对C语言课程的基本知识的理解和掌握 2 掌握C语言编程和程序调试的基本技能 3 利用C语言进行基本的软件设计 4 掌握书写程序设计说明文档的能力 5 提高运用C语言解决实际问题的能
  • es模糊查询

    Elasticsearch支持多种模糊查询 包括Wildcard查询 Fuzzy查询 Regexp查询和Match查询 这些查询可以用于执行模糊匹配 拼写纠错 范围查询等操作 下面是这些模糊查询的详细介绍 1 Wildcard 查询 Wil
  • 设置显示实体的颜色 byLayer/byBlock

    在CAD界面上显示时 其颜色属性可以设置为byLayer或者byBlock byLayer 实体的颜色和实体所在的图层保持一致 byBlock 实体的颜色和实体所在的块保持一致 但是 块中的实体都是一个个独立的对象 相互之间并没有直接的联系
  • JavaScript实现倒计时功能

    封装时间函数 代码如下 function getTime var t new Date var y t getFullYear var m t getMonth 1 gt 10 t getMonth 1 0 t getMonth 1 var
  • linux错误码_Linux 中断/异常的准备与退出

    本文讨论一下linux下x86平台关于中断 异常的准备与退出 主要关注点在于进入C语言部分前与退出C语言部分后汇编 C代码所处理的上下文切换部分 关于内容的说明 使用的内核版本为5 5 13 主要介绍64位下的内核实现 资料 引据都在最下方
  • 虚拟机实现服务器冗余,舰船公共计算服务虚拟机优化设置与冗余研究

    摘要 舰船公共计算服务中虚拟机优化设置与冗余方案是公共计算服务系统稳定性设计的一个关键问题 本文在保证舰船业务运行稳定的前提下 设计舰船刀片服务器虚拟机优化设置方案 追求舰船计算资源的高利用率 并针对舰船业务重要性与紧急性要求的不同 提出一
  • 【机器学习】集成学习+代码实现

    1 概念与分类 集成学习 ensemble learning 构建并结合多个学习器 先学习基学习器 再根据某种策略结合起来 结合可以是 集成不同算法 集成同一算法不同设置 数据集分成多部分分给不同分类器的集成 分类 bagging boos
  • 视觉基础算法

    找到一篇PPT 对于基础知识点的总结比较好 需要自己去深挖知识 链接 一 图片灰度化 灰度化有多种方式 可以根据自己的需求自己定制 这里列举三种常用的方式 将彩色图像的R G B三分量的亮度之一作为灰度图像灰度值 Gray B or Gra
  • 浏览器播放rtsp视频流方案(ffmpeg + nginx转m3u8)

    1 下载ffmpeg 传送门 https ffmpeg en softonic com 2 配置环境变量 右击我的电脑 gt 点击属性 打开左侧高级系统设置 点击下方的环境变量 在下方系统变量中找到path变量 选中点击下方编辑 别点成删除
  • 嵌入式---c语言变量范围及生命周期和定义声明

    嵌入式 c语言变量范围及生命周期 1 局部变量和全局变量 变量分为局部变量和全局变量 因为有的变量只能在本程序中使用 而有的变量可以在其他函数中使用 这就是变量作用域问题 1 1局部变量 定义 只能在一定范围内使用的变量称为局部变量 例如