0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言里变量的生命周期

DS小龙哥-嵌入式技术 来源:DS小龙哥-嵌入式技术 作者:DS小龙哥-嵌入式技 2023-07-11 09:12 次阅读

在 C 语言中,变量的生命周期指的是该变量存在的时间段,理解变量的内存释放时机,设计程序才能少出问题。

在程序执行期间,变量会经历以下三个阶段:

(1)定义阶段(定义变量):在定义变量时,编译器会为该变量分配内存空间。此时变量的值是不确定的。

(2)使用阶段(赋值、读取变量):在程序执行过程中,可以对变量进行赋值或读取操作。此时变量的值是确定的,并且会随着程序执行的进度而变化。

(3)销毁阶段(变量被销毁):在变量的作用域结束时,该变量就会被销毁。在这个过程中,编译器会自动释放该变量所占用的内存空间。

根据变量的定义位置和作用域,C 语言中的变量可以分为以下两种类型:

(1)局部变量:定义在函数内部或代码块内部的变量称为局部变量。局部变量只能在其定义所在的函数或代码块内部使用,并且在函数或代码块结束时被销毁。局部变量的生命周期受限于其所处的函数或代码块的生命周期。

(2)全局变量:定义在函数外部或文件顶部的变量称为全局变量。全局变量可以在整个程序中使用,其生命周期从程序开始到程序结束。全局变量在程序运行期间一直存在,并且在程序结束时才被销毁。

除了上述两种变量类型之外,C 语言还提供了另外一种特殊的变量类型——静态变量。静态变量定义在函数内部或代码块内部,但其生命周期与局部变量不同。静态变量在函数或代码块结束时不会被销毁,而是继续存在于内存中,并保留其上一次赋值的值,直到下一次被修改。

在 C 语言中,变量的生命周期是由其作用域和定义位置决定的。正确地管理变量的生命周期对于程序的正确性和性能都至关重要,程序员需要深入了解变量的生命周期,遵循正确的使用规则,确保程序的正确性和健壮性。

以下是使用代码进行举例说明变量的生命周期:

(1)定义阶段

在定义变量时,编译器会为该变量分配内存空间。

例如,在函数内部定义一个整型变量 a,其定义语句如下:

void foo() {
     int a;  // 定义变量
 }

此时变量 a 就被分配了内存空间,但其值是不确定的。

(2)使用阶段

在程序执行过程中,可以对变量进行赋值或读取操作。

例如,在上述定义变量的基础上,给变量 a 赋值并读取其值的代码如下:

void foo() {
     int a;  // 定义变量
 ​
     a = 10;  // 给变量赋值
     printf("a = %d
", a);  // 打印变量的值
 }

此时变量 a 的值已经确定为 10,并被输出到控制台。

(3)销毁阶段

在变量的作用域结束时,该变量就会被销毁。在这个过程中,编译器会自动释放该变量所占用的内存空间。例如,在上述定义变量和使用变量的代码基础上,添加一个条件语句使得变量 a 在条件成立之后被销毁,示例代码如下:

void foo() {
     int a;  // 定义变量
 ​
     a = 10;  // 给变量赋值
     printf("a = %d
", a);  // 打印变量的值if (a > 5) {
         int b = 20;  // 定义变量
         printf("b = %d
", b);  // 打印变量的值
     }
 ​
     printf("a = %d
", a);  // 打印变量的值,此时变量依然存在
 }

在上述代码中,当条件 a > 5 成立时,程序会在条件中定义并使用一个新的整型变量 b,但该变量在条件结束后就被释放了。而变量 a 的生命周期则受限于函数 foo() 的作用域,即在函数结束时被销毁。

(4)子函数返回地址(指针)

如果子函数返回指针变量,需要注意指针变量的生命周期问题,以避免指针失效和内存泄漏等问题。

假设有一个子函数 get_string(),该函数返回一个动态分配的字符串指针。函数定义及示例代码如下:

char* get_string() {
     char* str = (char*) malloc(10 * sizeof(char));
     str[0] = 'H';
     str[1] = 'e';
     str[2] = 'l';
     str[3] = 'l';
     str[4] = 'o';
     str[5] = '';
     return str;
 }
 ​
 int main() {
     char* s = get_string();
     printf("%s
", s);  // 输出 "Hello"
 ​
     // 此处应该手动释放内存
     free(s);
 ​
     return 0;
 }

在上述代码中,函数 get_string() 动态分配了一个长度为 10 的字符数组 str,并返回了该数组的首地址,该指针是在堆(heap)上分配的。由于是动态分配的内存空间,因此需要手动释放。在 main() 函数中对指针进行操作后,也需要手动释放该指针所指向的内存空间,以避免内存泄漏。

以下是一个错误的示例,用于和前面正确示例进行对比,帮助理解返回指针的生命周期问题:

char* get_string() {
     char str[] = "Hello";
     return str;
 }
 ​
 int main() {
     char* s = get_string();
     printf("%s
", s);  // 输出 "Hello"return 0;
 }

在这个示例中,函数 get_string() 返回了一个局部数组 str 的首地址。由于 str 是在函数内部定义的局部变量,其生命周期仅限于函数调用过程中。当函数 get_string() 执行完毕后,str 的生命周期已经结束,其内存空间已被回收,此时返回的指针变量 s 已经成为了野指针,指向了无效的内存空间,进而会导致未定义的行为。

尽管该函数定义的返回类型是 char*,但是由于返回了一个局部变量的指针,会导致指针失效、访问非法内存等问题,从而产生程序崩溃等错误行为。

总结:如果一个子函数需要返回指针变量,需要确保返回的指针指向的内存空间在使用期间有效,否则会导致严重的问题。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内存
    +关注

    关注

    8

    文章

    2767

    浏览量

    72765
  • C语言
    +关注

    关注

    180

    文章

    7530

    浏览量

    128664
  • 编程
    +关注

    关注

    88

    文章

    3440

    浏览量

    92389
  • 函数
    +关注

    关注

    3

    文章

    3868

    浏览量

    61309
  • 指针变量
    +关注

    关注

    0

    文章

    17

    浏览量

    7198
收藏 人收藏

    评论

    相关推荐

    基于Rust语言中的生命周期

    Animal的代码示例。 生命周期 生命周期是Rust语言中的一个概念,用于决内存安全问题。我们在Rust中定义一个变量时,需要确定这个变量
    的头像 发表于 09-19 17:03 601次阅读

    AutoScaling 生命周期挂钩功能

    摘要: AutoScaling 伸缩组实例管理功能全面升级,新上线生命周期挂钩(LifecycleHook)功能,方便用户更加灵活地管理伸缩组内实例。使用生命周期挂钩可以在伸缩组发生伸缩活动时将伸缩
    发表于 06-27 17:13

    请问C6720的生命周期还有多长?

    您好!因成本限制,有个产品想使用TMS320C6720BRFP200,但是不知道这个芯片的生命周期还有多长?谢谢!
    发表于 08-01 06:37

    理解数据生命周期管理思路

    数据生命周期管理的思考
    发表于 03-17 10:49

    HarmonyOS应用开发-PageAbility生命周期

    pageAbility的生命周期如下图所示:在代码中通过调用下列方法实现生命周期操作:onShow() :Ability由后台不可见状态切换到前台可见状态调用onShow方法,此时用户在屏幕可以看到
    发表于 10-17 11:11

    在S32G2 RM中有“生命周期”,生命周期的完整含义是什么?

    在S32G2 RM中,有“生命周期”。生命周期的完整含义是什么,我们应该如何使用它?
    发表于 04-23 10:37

    贯穿于全生命周期的功能安全

    简要介绍了功能安全在SIS 全安全生命周期的主要活动,叙述了全生命周期的功能安全管理。简要阐述了贯穿于整体安全生命周期的功能安全进行的主要阶段,同时提出了在设计SIS
    发表于 12-19 15:50 15次下载

    贯穿于全生命周期的功能安全

    简要介绍了功能安全在SIS 全安全生命周期的主要活动,叙述了全生命周期的功能安全管理。简要阐述了贯穿于整体安全生命周期的功能安全进行的主要阶段,同时提出了在设计SIS 时
    发表于 01-06 17:11 6次下载

    一文读懂Android Activity生命周期

    正常情况下Activity的生命周期: Activity的生命周期大概可以归为三部分 整个的生命周期:onCreate()可以设置所有的“全局”状态, onDestory()可以释放所有的资源 可见
    发表于 05-30 01:03 1370次阅读

    存储类&作用域&生命周期&链接属性

    七、链接属性前言本篇文章将会为大家介绍一些变量相关的存储属性、作用域、生命周期以及链接属性的一些知识,有助于大家更好地理解程序,分析程序。一、存储类&作用域&生命周期&链接属性的概念解析1、存储类(1)存
    发表于 12-09 15:51 5次下载
    存储类&作用域&<b class='flag-5'>生命周期</b>&链接属性

    Synopsys 启动硅生命周期管理计划

    Synopsis 的数据分析驱动的硅生命周期管理计划解决了 IC 生命周期中的质量、可靠性和安全挑战。
    发表于 08-18 15:37 628次阅读
    Synopsys 启动硅<b class='flag-5'>生命周期</b>管理计划

    Vue入门Vue的生命周期

    .生命周期 4.1生命周期是什么 Vue的生命周期, 就是Vue实例从创建到销毁的过程.
    的头像 发表于 02-06 16:16 657次阅读
    Vue入门Vue的<b class='flag-5'>生命周期</b>

    编译器的标准生命周期

    编译器的标准生命周期
    发表于 03-14 19:06 0次下载
    编译器的标准<b class='flag-5'>生命周期</b>

    编译器的标准生命周期

    编译器的标准生命周期
    发表于 07-05 19:32 0次下载
    编译器的标准<b class='flag-5'>生命周期</b>

    数据包的生命周期

    电子发烧友网站提供《数据包的生命周期.pdf》资料免费下载
    发表于 10-13 14:44 0次下载