簡體   English   中英

C 中的“返回”從根本上做了什么?

[英]What does 'return' fundamentally do in C?

直到今天,我對function返回語句的概念的理解是這樣的:

當控件到達 function 的末尾時,控件返回給調用者(函數)。 無論 function 是否有return語句,都會發生這種情況。


ISO C 退出()

在閱讀C 程序的終止時,我看到了來自 ISO C (7.22.4.4.6) 的聲明 -

出口 function 無法返回其調用者。

這種說法與我之前的理解相矛盾。


ISO C 退貨聲明

所以我檢查了 ISO C 對return語句的評論(6.8.6.4)並發現了這個:

  1. 帶有表達式的 return 語句不應出現在返回類型為 void 的 function 中。 沒有表達式的 return 語句只能出現在返回類型為 void 的 function 中。
  2. return 語句終止當前 function 的執行並將控制返回給其調用者。 function 可能有任意數量的返回語句。

我的新結論

  1. “返回”語句使宿主環境強制將控制權返回給調用者(函數)。
  2. 對於返回類型void的函數,如果它包含return語句,則宿主環境必須將控制權返回給調用者(函數)。 否則(即,如果不存在return語句),則宿主環境可能會將控制返回給調用者。
  3. 默認情況下,許多實現選擇將控制返回給調用者 function,即使被調用者 function 沒有return語句,但exit()的情況除外(此異常也可能擴展到其他一些函數)。

我的結論正確嗎?

您的功能在您的程序中。 它們不是宿主環境的一部分。 宿主環境在你的程序之外。 在普通的通用多用戶系統中,主機環境是操作系統(包括用於執行程序的命令行 shell 之類的東西)。

return語句返回到程序內部的調用函數。 流向 function 的結束}的程序控制將控制返回給調用 function。調用exit不會返回到程序內部的 function; 它向操作系統發出終止程序的請求。 (但是,在發出此最終請求之前, exit可能會執行各種清理工作並調用 exit 處理程序,因此程序中的某些函數可能仍會在程序終止之前執行。)

當然,您從標准中引用的所有內容都是正確的,並且沒有矛盾。

出口()

但是exit() function 的描述與 return 語句的作用無關。 這主要是因為它不包含一個,或者至少永遠不會包含一個。 它也永遠不會走到盡頭。 相反,它指示操作系統,例如 Linux 或 Windows,完全停止執行程序,而程序仍在執行退出 function。這就是exit()永遠不會返回的原因:它只是停止並從 memory 中刪除,而不是一起使用程序的 rest。 它不僅不返回; 沒有什么可以返回的了。

函數調用和返回

function 調用本質上是跳轉到不同的機器代碼指令,加上一些細節。 例如,存儲我們跳轉的地址,以便我們知道在 function 結束時從哪里繼續,arguments 存儲在某個地方,以便被調用的 function 可以訪問它們。 從 function 返回也是一次跳轉到記憶的返回地址,加上一些細節,比如將返回值(如果有的話)放在調用者可以訪問的地方。 到達 function 的末尾完全等同於擊中 return 語句,沒有功能差異。

“調用”function 的代碼以及從中返回的代碼完全由編譯器生成。 不涉及操作系統。 該代碼是編譯器生成的二進制文件的一部分。

使用操作系統設施

相比之下,終止程序是每個操作系統為程序提供的基本服務之一。 執行此操作的代碼不是程序的一部分,而是操作系統的一部分,如 Linux 或 Windows。想要使用此類操作系統服務的程序必須進行系統調用2 Windows 下的一個這樣的調用可能是ExitProcess() ,這可能是 C 標准庫的exit()實現在某個時刻調用的 Windows。因為這將導致 Windows 停止當前進程,在exit()之后的代碼永遠不會執行,包括任何將控制返回給調用 function 的代碼,例如main()

C 程序在操作系統之間可移植的原因之一是一個包裝器,它保護 C 程序免受任何給定操作系統1的特殊性:標准 C 庫。

如果沒有標准庫,C 的 Windows 程序將調用ReadFile()ExitProcess()而 Posix 程序將調用read()_exit() 將程序從一個操作系統移植到另一個操作系統需要更改源代碼。 相比之下,僅使用標准庫調用fread()exit()的 C 程序(該頁面包含 Posix 平台特定_exit() function 以及標准 C 庫 function exit()的文檔)將重新在具有帶標准庫的 C 編譯器的任何平台上編譯:適應新操作系統只需一次,然后可用於所有程序。

你的問題

現在我們可以回答您的問題了。

  1. 不, return語句不會引起與操作系統的任何交互。 一切都在運行過程中,沒有任何系統資源被使用或釋放。 3個

  2. 因為return語句或因為到達 function 的末尾而返回是完全等價的。 生成的代碼是完全等價的。 在這兩種情況下,都必須將控制流返回給調用方 function。 exit() function 不返回的原因是因為它在到達結束或返回語句之前終止了進程。如果它確實到達其中任何一個,它將返回並且調用者將恢復執行。)

  3. 這在上一段中已經回答; 只是為了澄清:當達到 function 的末尾時,符合要求的實現不能自由選擇返回或不返回調用者; 它總是必須這樣做。 exit() function 永遠不會結束。


1值得注意的是,操作系統本身已經提供了一個標准化層:每個使用 Windows API 的程序都可以使用ReadFile() ,與特定機器上使用的特定文件系統和 I/O 芯片組無關。 C 標准庫是這些抽象層之上的抽象/標准化層。

2我在這里將“系統調用”稍微寬松地用作“本機操作系統 API 中的函數”。

3除非 function 在單獨的任務中執行,這完全是另一回事。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM