简体   繁体   English

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

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

Till today my understanding of the concepts function and return statement was like this:直到今天,我对function返回语句的概念的理解是这样的:

When the control reaches the end of a function, the control is returned back to the caller (function).当控件到达 function 的末尾时,控件返回给调用者(函数)。 This happens regardless of whether the function has a return statement or not.无论 function 是否有return语句,都会发生这种情况。


ISO C on exit() ISO C 退出()

While reading about termination of a C program , I saw a statement from ISO C (7.22.4.4.6) -在阅读C 程序的终止时,我看到了来自 ISO C (7.22.4.4.6) 的声明 -

The exit function cannot return to its caller.出口 function 无法返回其调用者。

This statement was contradicting to my previous understanding.这种说法与我之前的理解相矛盾。


ISO C on return statement ISO C 退货声明

So I checked ISO C's comment (6.8.6.4) on return statement and found this:所以我检查了 ISO C 对return语句的评论(6.8.6.4)并发现了这个:

  1. A return statement with an expression shall not appear in a function whose return type is void.带有表达式的 return 语句不应出现在返回类型为 void 的 function 中。 A return statement without an expression shall only appear in a function whose return type is void.没有表达式的 return 语句只能出现在返回类型为 void 的 function 中。
  2. A return statement terminates execution of the current function and returns control to its caller. return 语句终止当前 function 的执行并将控制返回给其调用者。 A function may have any number of return statements. function 可能有任意数量的返回语句。

My new conclusion我的新结论

  1. The 'return' statement makes the host environment to compulsarily return control to the caller (function). “返回”语句使宿主环境强制将控制权返回给调用者(函数)。
  2. In case of functions with return type of void , if it contains the return statement, then the host environment must return back control to the caller (function).对于返回类型void的函数,如果它包含return语句,则宿主环境必须将控制权返回给调用者(函数)。 Else (ie, if return statement is not present), then host environment may return control to the caller.否则(即,如果不存在return语句),则宿主环境可能会将控制返回给调用者。
  3. Many implementations, by default, choose to return back control to the caller function, even if the callee function doesn't have return statement, but except in the case of exit() (this exception maybe extended to some other functions as well).默认情况下,许多实现选择将控制返回给调用者 function,即使被调用者 function 没有return语句,但exit()的情况除外(此异常也可能扩展到其他一些函数)。

Are my conclusions correct?我的结论正确吗?

Your functions are inside your program.您的功能在您的程序中。 They are not part of the host environment.它们不是宿主环境的一部分。 The host environment is outside your program.宿主环境在你的程序之外。 In an ordinary general-purpose multi-user system, the host environment is the operating system (including things like a command-line shell used to execute programs).在普通的通用多用户系统中,主机环境是操作系统(包括用于执行程序的命令行 shell 之类的东西)。

return statements return to calling functions inside your program. return语句返回到程序内部的调用函数。 Program control flowing to the closing } of a function returns control to the calling function. Calling exit does not return to a function inside your program;流向 function 的结束}的程序控制将控制返回给调用 function。调用exit不会返回到程序内部的 function; it makes a request to the operating system to terminate the program.它向操作系统发出终止程序的请求。 (However, before making this final request, exit may perform various clean-up work and call exit handlers, so some functions within your program may still execute before the program is terminated.) (但是,在发出此最终请求之前, exit可能会执行各种清理工作并调用 exit 处理程序,因此程序中的某些函数可能仍会在程序终止之前执行。)

All you quote from the standard is, of course, correct, and not contradicting.当然,您从标准中引用的所有内容都是正确的,并且没有矛盾。

exit()出口()

But the description of the exit() function has nothing to do with what a return statement does.但是exit() function 的描述与 return 语句的作用无关。 That is mainly because it does not contain one, or at least never reaches one.这主要是因为它不包含一个,或者至少永远不会包含一个。 It also never reaches its end.它也永远不会走到尽头。 Instead, it instructs the operating system, eg Linux or Windows, to stop executing the program entirely, while the program still is executing the exit function. This is why exit() never returns: It simply stops and is removed from memory instead, together with the rest of the program.相反,它指示操作系统,例如 Linux 或 Windows,完全停止执行程序,而程序仍在执行退出 function。这就是exit()永远不会返回的原因:它只是停止并从 memory 中删除,而不是一起使用程序的 rest。 Not only does it not return;它不仅不返回; there is nothing left to return to.没有什么可以返回的了。

Calling and returning from functions函数调用和返回

A function call is essentially a jump to a different machine code instruction, plus some niceties. function 调用本质上是跳转到不同的机器代码指令,加上一些细节。 For example, the address from which we are jumping is stored so that we know where to continue when the function has ended, and arguments are stored somewhere so that the called function can access them.例如,存储我们跳转的地址,以便我们知道在 function 结束时从哪里继续,arguments 存储在某个地方,以便被调用的 function 可以访问它们。 Returning from a function is, again, a jump, to the memorized return address, plus some niceties like putting the return value, if any, in a place where the caller can access it.从 function 返回也是一次跳转到记忆的返回地址,加上一些细节,比如将返回值(如果有的话)放在调用者可以访问的地方。 Reaching the end of a function is exactly equivalent to hitting a return statement, there is no functional difference.到达 function 的末尾完全等同于击中 return 语句,没有功能差异。

The code that "calls" a function, and the code that returns from it, is entirely produced by the compiler. “调用”function 的代码以及从中返回的代码完全由编译器生成。 The operating system is not involved.不涉及操作系统。 The code is part of the binary the compiler has produced.该代码是编译器生成的二进制文件的一部分。

Using operating system facilities使用操作系统设施

Terminating a program , by contrast, is one of the basic services every operating system provides to programs.相比之下,终止程序是每个操作系统为程序提供的基本服务之一。 The code that does that is not part of the program but of the operating system like Linux or Windows. Programs which want to utilize such operating system services must make system calls 2 .执行此操作的代码不是程序的一部分,而是操作系统的一部分,如 Linux 或 Windows。想要使用此类操作系统服务的程序必须进行系统调用2 One such call under Windows could be ExitProcess() , which is perhaps what gets called at some point by the C Standard Library's exit() implementation for Windows. Because this will cause Windows to stop the current process, code after that in exit() is never executed, including any code that would return control to the calling function, eg main() . Windows 下的一个这样的调用可能是ExitProcess() ,这可能是 C 标准库的exit()实现在某个时刻调用的 Windows。因为这将导致 Windows 停止当前进程,在exit()之后的代码永远不会执行,包括任何将控制返回给调用 function 的代码,例如main()

One of the reasons that C programs are portable between operating systems is a wrapper that shields C programs from the particularities of any given operating system 1 : The Standard C Library. C 程序在操作系统之间可移植的原因之一是一个包装器,它保护 C 程序免受任何给定操作系统1的特殊性:标准 C 库。

Without the standard library, a C program for Windows would call eg ReadFile() or ExitProcess() while a Posix program would call read() or _exit() .如果没有标准库,C 的 Windows 程序将调用ReadFile()ExitProcess()而 Posix 程序将调用read()_exit() Porting a program from one operating system to another would make changes to the source code necessary.将程序从一个操作系统移植到另一个操作系统需要更改源代码。 By contrast, a C program using only the standard library calls fread() and exit() (that page contains both the documentation for the Posix platform specific _exit() function as well as the Standard C library function exit() ) will re-compile on any platform that has a C compiler with a standard library: The adaptation to a new operating system is necessary only once and is then available to all programs.相比之下,仅使用标准库调用fread()exit()的 C 程序(该页面包含 Posix 平台特定_exit() function 以及标准 C 库 function exit()的文档)将重新在具有带标准库的 C 编译器的任何平台上编译:适应新操作系统只需一次,然后可用于所有程序。

Your questions你的问题

Now we are able to answer your questions.现在我们可以回答您的问题了。

  1. No, the return statement does not cause any interaction with the operating system.不, return语句不会引起与操作系统的任何交互。 Everything stays within the running process, and no system resources whatsoever are used or freed.一切都在运行过程中,没有任何系统资源被使用或释放。 3 3个

  2. Returning because of a return statement or because the end of the function is reached is exactly equivalent.因为return语句或因为到达 function 的末尾而返回是完全等价的。 The code generated is exactly equivalent .生成的代码是完全等价的。 Returning the control flow to the calling function is mandatory in both cases.在这两种情况下,都必须将控制流返回给调用方 function。 (The reason the exit() function does not return is because it terminates the process before it reaches either its end or a return statement. If it did reach either one, it would return and the caller would resume execution.) exit() function 不返回的原因是因为它在到达结束或返回语句之前终止了进程。如果它确实到达其中任何一个,它将返回并且调用者将恢复执行。)

  3. This is answered in the previous paragraph;这在上一段中已经回答; just to clarify: A conforming implementation is not free to choose between returning or not returning to the caller when the end of function is reached;只是为了澄清:当达到 function 的末尾时,符合要求的实现不能自由选择返回或不返回调用者; it always must do so.它总是必须这样做。 The exit() function simply never reaches its end. exit() function 永远不会结束。


1 It is noteworthy that the operating system itself already provides a standardization layer: Every program using the Windows API can use ReadFile() , independent of the particular file system and I/O chipset used on the specific machine. 1值得注意的是,操作系统本身已经提供了一个标准化层:每个使用 Windows API 的程序都可以使用ReadFile() ,与特定机器上使用的特定文件系统和 I/O 芯片组无关。 The C Standard Library then is an abstraction/standardization layer on top of those abstraction layers. C 标准库是这些抽象层之上的抽象/标准化层。

2 I use "system call" here a bit loosely as "function in the native OS API". 2我在这里将“系统调用”稍微宽松地用作“本机操作系统 API 中的函数”。

3 Unless the function is executed in a separate task, which is a different matter altogether. 3除非 function 在单独的任务中执行,这完全是另一回事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM