回覆列表
  • 1 # IT劉小虎

    C語言函式的區域性變數在函式執行完畢後,會被釋放,相信即使是C語言初學者,也是瞭解這一點的。不過,我們在函式中定義一個區域性變數,卻是可以透過 return 語法將其返回給呼叫者的,這也許就是題主的疑惑之處。

    C語言函式怎麼可以把一個被釋放的值返回給呼叫者使用呢?

    請看下面這張圖,進一步來說,C語言程式每呼叫一個函式,就會在棧區為其分配一塊區域,所有區域性變數都是在這塊區域裡存放的,函式執行完畢返回後,系統自動就將這塊區域收回了。

    這塊區域較為正式的名字叫“棧幀”。

    既然函式的區域性變數都存放在棧區,棧區在函式返回就釋放了,那為什麼 add 函式還能把區域性變數返回呢?

    其實函式返回的並不是區域性變數,而是區域性變數裡面存放的資料

    我們用鞋櫃來比喻區域性變數,用鞋子來比喻資料。我們想取出的是鞋子,而不是鞋櫃,對嗎?

    以我的機器為例,在函式執行完畢後,系統會先將返回值暫存在暫存器 eax 裡,所以即使函式的棧幀被系統收回了,它的返回值依然在 eax 裡儲存的很好。函式返回後,系統再把返回值從 eax 中取出,賦值給呼叫者。請看下面這個例子:

    我們檢視它的彙編程式碼,發現一切和我們預料的一致:

    從彙編程式碼可以看出,C語言的 return 實際上返回的是是將區域性變數裡的值,而不是直接返回區域性變數。

    不過,因為返回值是存放在區域性變數裡的,而區域性變數被釋放了,所以必須再為該值找一個“容器”,該“容器”在本例中就是 eax 暫存器。

    總結一下

    題目所說的“C語言函式返回區域性變數”這一過程是這樣的:在區域性變數被釋放之前,C語言程式將存放在其中的值暫時存放到 eax 暫存器中,eax 是不會被釋放的,所以函式執行完畢後,return 仍然能將其中的值返回給呼叫者。

  • 2 # 周林ZhouLin

    看了底下兄弟的答覆,只能說答對了一半。

    真正的原因在於ABI(應用程式二進位制介面)。

    ABI定義了與系統互動的細節:如資料型別、大小和對齊;呼叫約定(控制函式的引數的傳遞方向、可變長度處理、堆疊清理主體以及如何接受返回值等);系統呼叫的編碼和一個應用如何向作業系統進行系統呼叫;以及在一個完整的作業系統ABI中,目標檔案的二進位制格式、程式庫等等。一個完整的ABI,像Intel二進位制相容標準 (iBCS),允許支援它的作業系統上的程式不經修改在其他支援此ABI的操作體統上執行。

    其他的 ABI 標準化細節還包括 C++ 名稱修飾 ,和同一個平臺上的編譯器之間的呼叫約定,但是不包括跨平臺的相容性。

    至於底下兄弟所說的EAX儲存返回值,這個只是X86的ABI規範,在PowerPC等其他CPU架構平臺,實現是不一樣的!——PowerPC下,返回值是儲存在R3暫存器中的

  • 3 # 壹仁說

    在C語言中,區域性變數的作用域只在函式內部,在函式返回後,區域性變數的記憶體就會被釋放。如果函式只是返回區域性變數,那麼這個區域性變數會被複制一份傳回被呼叫處。但是如果函式返回的是區域性變數的地址,那麼就會報錯,因為函式只是把指標複製後返回了,但是指標指向的內容已經被釋放,這樣指標指向的內容就是不可預料的內容,程式就會出錯。準確的來說,函式不能透過返回指向棧記憶體的指標(返回指向堆記憶體的指標是可以的)。

  • 中秋節和大豐收的關聯?
  • 復聯4美國隊長為什麼把盾牌給鷹眼而不是給他從小玩到大的巴基?