在调用函数returning int 后,在非void 函数中调用return 的结果是什么?

What is the result of calling return in a non-void function after calling a function returning int?

2018 年更新:这是我写的一个老问题,对 C 的理解有所减少。请不要投票。


当我使用以下代码时:

int mytest(void);
int main(void)
{
   mytest();
   return;
}
int mytest(void)
{
   return 3;
}

main 的 return 值是多少?我明白这是

Edit: large comment: I know this is undefined behavior. Logically, what return value will be produced?

Edit 2: Sample: http://ideone.com/fAxnNn

这不是期望的行为,尽管没有明确提及为未定义的行为。这是一个"Constraints violation".

引用 C11,第 6.8.6.4 章

[...] A return statement without an expression shall only appear in a function whose return type is void.

并且,从第 §5.1.1.3 章开始,诊断

A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. [....]

在这种情况下,编译器继续生成可执行代码,因此,是的,执行此二进制文件会调用 undefined behavior

底线,对于预期 return 的 main()int 不应该有没有表达式的 return 语句。避免编写这样的代码。


[注意:As per this discussion,有一种强烈的观念认为这是未定义的行为,但仍然没有显式在标准中提到。]

显示的程序不是合法的 C。在这样的非空函数中使用 return; 约束违规 ,并且需要您的编译器抱怨。通常,这将是一个错误,但允许编译器生成程序——但标准显然没有对此类程序的行为提出任何要求。因此它的行为未定义(从技术上讲,这与未定义行为略有不同,因为它没有在标准中明确指定为“undefined”)。

问这样的问题是没有意义的,“当我导致未定义的行为时会发生什么?”,因为答案总是,“任何事情 ."

顺便说一句,您可以 省略 一个 return 语句(即 运行 关闭函数的末尾) 只要您的程序不使用 return 值 。如果程序使用 return 值,则行为是未定义的(不仅仅是未指定)。特别是,运行关闭 main() 的末尾是合法的。虽然没有理由允许没有 return 的函数,但不允许有显式 void return 的函数,我认为这是由于函数的结束是否可到达的逻辑不确定性(这是暂停问题的一个例子) ).

在这种情况下特别感兴趣的是所讨论的函数是 main()。编译器可用的选项(除了发出所需的诊断信息之外)包括(但不限于):

  • 终止编译
  • return; 优化为函数中的最后一条语句,并将其视为与 main() 相同,没有 return 语句
  • Return 一个未初始化的值(可能是支持它们的体系结构上的信号值,或者它可能是最近使用的堆栈值,或者其他的东西)

从评论中(不是从问题中),我了解到主要目的是通过 return; 找到 main 返回的内容。我希望我正朝着正确的方向前进。

第一件事 很少有编译器允许只写 return; 并且有些编译器会给出警告并且一些编译器会隐式添加 return 0; 如果没有返回主.

第二件事 返回 0 表示程序成功执行,如果返回任何其他内容将意味着一些 运行 时间错误(至少您的环境是这样认为的)。

现在你的疑问来了:main 通过写 return; 隐式返回了什么。我检查了您使用的工具 ideone.com 和 C (gcc-5.1)。

有了return;它给了

Runtime error   time: 0 memory: 2164 signal:-1

有了return 0;它给了

Success time: 0 memory: 2164 signal:0

有了return 1;它又给了

Runtime error   time: 0 memory: 2164 signal:-1

在这个信号中表示从main

返回的值

如果您使用终端运行您的程序,您可以使用echo $?获取返回值。

所以现在您可以自己观察 return;return 1; 给出相同的输出(返回的隐式值也可能是垃圾)。尽管如此,我们仍不能保证这一点,但现在您拥有查找所需的所有工具。

这里的问题是你似乎不明白 undefined behavior 的意思。

当你调用未定义的行为时,任何事情都可能发生。您的程序可能会崩溃,可能会产生意想不到的结果,或者看起来工作正常。进行看似无关的更改,例如添加未使用的变量或额外调用 printf,可以改变未定义行为的表现方式。

这也意味着两个不同的编译器可以为相同的代码生成不同的结果,或者具有两个不同优化设置的一个编译器可以生成不同的结果。

我举个例子。我使用 gcc 4.1.2 在 CentOS 5.10 上编译了您的原始代码。首先我在没有任何优化的情况下编译:

gcc -Wall -Wextra -g -o /tmp/x1 /tmp/x1.c

我运行结果代码然后运行echo $?。后者打印前一个进程的退出代码(即 main 的 return 值)。结果:

[dbush@db-centos tmp]$ /tmp/x1
[dbush@db-centos tmp]$ echo $?
3
[dbush@db-centos tmp]$ 

现在我将在 Visual Studio 2010 下的 Windows 7 机器上编译相同的代码:

cl x1.c

如果我 运行 然后 echo %ERRORLEVEL% 打印 return 代码,我得到这个:

C:\Users\dbush\Documents>x1

C:\Users\dbush\Documents>echo %ERRORLEVEL%
0

C:\Users\dbush\Documents>

如您所见,gcc 和 MSVC 为相同的代码生成不同的结果。在一种情况下它 returns 3 而在另一种情况下它 return 0.

现在让我们开始优化。我在同一台 CentOS 机器上用相同版本的 gcc 编译了相同的代码,但打开了优化:

gcc -Wall -Wextra -g -o /tmp/x1 /tmp/x1.c -O3

然后我运行这两次。然后我得到以下结果:

[dbush@db-centos tmp]$ /tmp/x1
[dbush@db-centos tmp]$ echo $?
68
[dbush@db-centos tmp]$ /tmp/x1
[dbush@db-centos tmp]$ echo $?
36
[dbush@db-centos tmp]$ 

因此,当 运行 不同的优化设置时,我不仅会得到不同的结果,而且 运行 多次 相同的程序 也会得到不同的结果。这就是未定义行为可能发生的情况。

所以要回答您的问题 "what return value will be produced",答案取决于您调用了未定义的行为。你无法可靠地预测会发生什么。

编辑:

更新代码的更多示例。

在没有优化的 gcc 上:

[dbush@db-centos tmp]$ /tmp/x1
mytest2 = 3
[dbush@db-centos tmp]$ echo $?
12

在优化的 gcc 上 -O3:

[dbush@db-centos tmp]$ /tmp/x1
mytest2 = -1078711820
[dbush@db-centos tmp]$ echo $?
22
[dbush@db-centos tmp]$ /tmp/x1
mytest2 = -1077511916
[dbush@db-centos tmp]$ echo $?
22

在没有优化的 MSVC 上:

C:\Users\dbush\Documents>x1
mytest2 = 3

C:\Users\dbush\Documents>echo %ERRORLEVEL%
0

C:\Users\dbush\Documents>

在经过优化的 MSVC 上 /Ox:

C:\Users\dbush\Documents>x1
mytest2 = 1

C:\Users\dbush\Documents>echo %ERRORLEVEL%
0

C:\Users\dbush\Documents>

再说一次,没有 gua运行T 恤。