[英]What does 'return' fundamentally do in C?
直到今天,我對function和返回語句的概念的理解是這樣的:
當控件到達 function 的末尾時,控件返回給調用者(函數)。 無論 function 是否有
return
語句,都會發生這種情況。
在閱讀C 程序的終止時,我看到了來自 ISO C (7.22.4.4.6) 的聲明 -
出口 function 無法返回其調用者。
這種說法與我之前的理解相矛盾。
所以我檢查了 ISO C 對return
語句的評論(6.8.6.4)並發現了這個:
- 帶有表達式的 return 語句不應出現在返回類型為 void 的 function 中。 沒有表達式的 return 語句只能出現在返回類型為 void 的 function 中。
- return 語句終止當前 function 的執行並將控制返回給其調用者。 function 可能有任意數量的返回語句。
- “返回”語句使宿主環境強制將控制權返回給調用者(函數)。
- 對於返回類型為
void
的函數,如果它包含return
語句,則宿主環境必須將控制權返回給調用者(函數)。 否則(即,如果不存在return
語句),則宿主環境可能會將控制返回給調用者。- 默認情況下,許多實現選擇將控制返回給調用者 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 編譯器的任何平台上編譯:適應新操作系統只需一次,然后可用於所有程序。
現在我們可以回答您的問題了。
不, return
語句不會引起與操作系統的任何交互。 一切都在運行過程中,沒有任何系統資源被使用或釋放。 3個
因為return
語句或因為到達 function 的末尾而返回是完全等價的。 生成的代碼是完全等價的。 在這兩種情況下,都必須將控制流返回給調用方 function。 ( exit()
function 不返回的原因是因為它在到達結束或返回語句之前終止了進程。如果它確實到達其中任何一個,它將返回並且調用者將恢復執行。)
這在上一段中已經回答; 只是為了澄清:當達到 function 的末尾時,符合要求的實現不能自由選擇返回或不返回調用者; 它總是必須這樣做。 exit()
function 永遠不會結束。
1值得注意的是,操作系統本身已經提供了一個標准化層:每個使用 Windows API 的程序都可以使用ReadFile()
,與特定機器上使用的特定文件系統和 I/O 芯片組無關。 C 標准庫是這些抽象層之上的抽象/標准化層。
2我在這里將“系統調用”稍微寬松地用作“本機操作系統 API 中的函數”。
3除非 function 在單獨的任務中執行,這完全是另一回事。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.