我正在学习C ++。下面的代码让我感到困惑:
int test_return(int a)
{
for (int i = 40; i < 44; i++)
{
if (i == a)
{
cout << "return here with i: " << i << endl;
return 59;
}
}
}
int main()
{
cout << "in main: " << test_return(61) << endl;
return 0;
}
我知道我在函数test_return
的末尾缺少一个return语句。
但编译器说没有错误,它在执行时有效。
因此,我会选择一些特定的数字,例如40
,44
,59
,61
,以查看函数test_return
将选择返回哪一个。
我试了几次,输出总是这样:
in main: 44
似乎函数test_return
在for语句结束之前返回了int i
。
我的问题是:
这合法吗?
它是如何运作的?
更新:
我在函数test_return
的末尾添加了这些代码:
int i = 100;
int square = i * i;
它出来了:
in main: 10000
感谢@Vlad来自莫斯科的回答!它会有所帮助。
答案 0 :(得分:6)
如果有兼容英特尔的计算机,那么该函数似乎会将结果返回到寄存器EAX
。
同时该函数将此寄存器用于变量i。
因此循环后寄存器总是包含44。
此值接收来电者。
当然,该函数具有未定义的行为。它应该有一个显式的return语句,在循环之后的函数末尾有一个表达式。
答案 1 :(得分:2)
但编译器说没有错误,它在执行时有效。
这取决于您的警告级别。
例如,MSVC在使用/W1
到/W4
之类的任何内容进行编译时说:
warning C4715: 'test_return' : not all control paths return a value
您甚至可以使用/WX
选项将警告变为错误:
error C2220: warning treated as error - no 'object' file generated
warning C4715: 'test_return' : not all control paths return a value
GCC或其他编译器有类似的选择。只需阅读文档或研究Google中的选项。
C ++的理念是,如果他们不仔细考虑他们的编译器设置,使用低警告级别或忽略警告,那就是开发人员的错。如果您执行上述任何操作,那么结果通常是在运行时未定义的行为,就像您的情况一样(缺少返回值)。
您还应该知道C ++标准不区分错误和警告;它只知道所谓的“诊断信息”。编译器是否应将这些变为警告或错误并不是强制要求的。但是,缺少返回值不需要此类诊断消息。因此,从C ++标准的角度来看,您收到的代码警告(或错误)是可选的。没关系,因为即使在不需要诊断消息的情况下,编译器也可以自由提供更多输出。
顺便说一句......
执行时有效。
这只是一个巧合。未定义的行为意味着一切都会发生,包括不时出现的所需行为。