直到今天,我对函数和返回语句的理解是这样的:
当控制到达函数末尾时,控制返回给调用方(函数),无论函数是否有return
语句。
退出时使用ISO C()
在阅读有关终止C程序的内容时,我看到ISO C(7.22.4.4.6)中的一条声明-
exit函数无法返回到其调用方。
这个说法与我以前的理解相矛盾。
ISO C on return语句
因此,我检查了ISO C对return
语句的注解(6.8.6.4),发现如下内容:
1.带表达式的return语句不应出现在返回类型为void的函数中。不带表达式的return语句只能出现在返回类型为void的函数中。
- return语句终止当前函数的执行并将控制权返回给调用者。一个函数可以有任意数量的return语句。
我的新结论
1.“return”语句使宿主环境强制将控制返回给调用者(函数)。
1.在具有void
的返回类型的函数的情况下,如果它包含return
语句,则主机环境必须将控制返回给调用者(函数)。否则(即,如果return
语句不存在),则主机环境可以将控制返回给调用者。
1.默认情况下,许多实现选择将控制权返回给调用方函数,即使被调用方函数没有return
语句,但exit()
除外(此异常也可能扩展到其他一些函数)。
我的结论正确吗
2条答案
按热度按时间km0tfn4u1#
你的函数在你的程序内部,它们不是宿主环境的一部分。宿主环境在你的程序外部。在一个普通的通用多用户系统中,宿主环境是操作系统(包括像用于执行程序的命令行shell这样的东西)。
return
语句返回到程序内的调用函数。流向函数的结束}
的程序控制将控制返回到调用函数。调用exit
不会返回到程序内的函数;它会向操作系统发出终止程序的请求(但是,在发出最后一个请求之前,exit
可能会执行各种清理工作并调用退出处理程序,因此在程序终止之前,程序中的某些函数可能仍在执行)。jhdbpxl92#
当然,你从标准中引用的所有内容都是正确的,没有矛盾。
退出()
但是
exit()
函数的描述与return语句的作用无关,主要是因为它不包含return语句,或者说从来没有到达return语句,也从来没有到达return语句的末尾,而是指示Linux或Windows等操作系统完全停止执行该程序。而程序仍在执行exit函数。这就是exit()
从不返回的原因:它只是简单地停止并从内存中删除,与程序的其余部分一起。它不仅不返回;就没有什么可以回去了。从函数调用和返回
函数调用本质上是跳转到不同的机器码指令,再加上一些细节。例如,我们要跳转的地址被存储起来,这样我们就知道函数结束时要继续到哪里,参数被存储在某个地方,这样被调用的函数就可以访问它们。从函数返回也是跳转到存储的返回地址。再加上一些细节,比如把返回值(如果有的话)放在调用者可以访问它的地方。到达函数的末尾完全等同于命中一个return语句,没有功能上的区别。
“调用”函数的代码以及从函数返回的代码完全由编译器生成,与操作系统无关,这些代码是编译器生成的二进制代码的一部分。
使用操作系统工具
ExitProcess()
,这可能是Windows的C标准库的exit()
实现在某个时候调用的。因为这将导致Windows停止当前进程,所以exit()
中的该代码之后的代码永远不会执行,包括将控制返回给调用函数的任何代码,例如main()
。C程序可以在不同操作系统之间移植的原因之一是有一个 Package 器,它可以保护C程序不受任何给定操作系统特性的影响1:标准C库。
如果没有标准库,Windows的C程序将调用
ReadFile()
或ExitProcess()
,而Posix程序将调用read()
或_exit()
。将程序从一个操作系统移植到另一个操作系统将需要更改源代码。相反,仅使用标准库的C程序调用fread()
和exit()
(该页面包含Posix平台特定_exit()
函数以及标准C库函数exit()
的文档)将在具有标准库的C编译器的任何平台上重新编译:适应新的操作系统只需要一次,然后所有程序都可以使用。你的问题
现在我们能够回答您的问题。
1.不,
return
语句不会引起与操作系统的任何交互,所有内容都停留在正在运行的进程中,不会使用或释放任何系统资源。31.由于
return
语句或由于到达函数末尾而返回是完全等效的。生成的代码是exactly equivalent。在这两种情况下,都必须将控制流返回到调用函数。(exit()
函数不返回的原因是它在到达其end或return语句之前终止了进程。如果它确实到达了其中之一,它将返回并且调用者将继续执行)。1.这一点已在上一段作了回答;只是澄清一下:当到达函数末尾时,一致性实现不能自由地选择返回或不返回调用者;它总是必须这样做。
exit()
函数永远不会到达它的结尾。1值得注意的是,操作系统本身已经提供了标准化层:每个使用Windows API的程序都可以使用
ReadFile()
,而与特定计算机上使用的特定文件系统和I/O芯片组无关。C标准库是这些抽象层之上的一个抽象/标准化层。2我在这里使用“系统调用”作为“本机OS API中的函数”时有点松散。
3除非函数在单独的任务中执行,这完全是另一回事。