<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
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

    文章

    2776

    瀏覽量

    72849
  • C語言
    +關注

    關注

    180

    文章

    7538

    瀏覽量

    130270
  • 編程
    +關注

    關注

    88

    文章

    3444

    瀏覽量

    92549
  • 函數
    +關注

    關注

    3

    文章

    4042

    瀏覽量

    61390
  • 指針變量
    +關注

    關注

    0

    文章

    17

    瀏覽量

    7199
收藏 人收藏

    評論

    相關推薦

    基于Rust語言中的生命周期

    Animal的代碼示例。 生命周期 生命周期是Rust語言中的一個概念,用于決內存安全問題。我們在Rust中定義一個變量時,需要確定這個變量
    的頭像 發表于 09-19 17:03 ?623次閱讀

    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 ?1385次閱讀

    存儲類&作用域&生命周期&鏈接屬性

    七、鏈接屬性前言本篇文章將會為大家介紹一些變量相關的存儲屬性、作用域、生命周期以及鏈接屬性的一些知識,有助于大家更好地理解程序,分析程序。一、存儲類&作用域&生命周期&鏈接屬性的概念解析1、存儲類(1)存
    發表于 12-09 15:51 ?5次下載
    存儲類&作用域&<b class='flag-5'>生命周期</b>&鏈接屬性

    Synopsys 啟動硅生命周期管理計劃

    Synopsis 的數據分析驅動的硅生命周期管理計劃解決了 IC 生命周期中的質量、可靠性和安全挑戰。
    發表于 08-18 15:37 ?645次閱讀
    Synopsys 啟動硅<b class='flag-5'>生命周期</b>管理計劃

    Vue入門Vue的生命周期

    .生命周期 4.1生命周期是什么 Vue的生命周期, 就是Vue實例從創建到銷毀的過程.
    的頭像 發表于 02-06 16:16 ?673次閱讀
    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次下載
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>