与Java不同,C/C++中以下内容是允许的:
int* foo ()
{
if(x)
return p;
// What if control reaches here?
}
这经常导致崩溃,并且很难调试问题。为什么标准不强制要求非void函数有一个最终返回值? (编译器会为错误的return
值生成一个错误。)
在GCC或MSVC中是否有一个标志可以强制执行此操作?(类似于-Wunused-result
)
与Java不同,C/C++中以下内容是允许的:
int* foo ()
{
if(x)
return p;
// What if control reaches here?
}
这经常导致崩溃,并且很难调试问题。为什么标准不强制要求非void函数有一个最终返回值? (编译器会为错误的return
值生成一个错误。)
在GCC或MSVC中是否有一个标志可以强制执行此操作?(类似于-Wunused-result
)
这是不被允许的(未定义行为)。但是,标准在这种情况下不要求诊断。
由于存在以下代码,标准并不要求最后一个语句为return
:
while (true) {
if (condition) return 0;
}
这段代码总是返回0,但是一个愚蠢的编译器没能发现它。请注意,标准并不要求智能编译器。在while
块后加上return
语句是浪费的,而愚蠢的编译器无法优化掉它。标准不想要求程序员编写无用代码,只是为了满足一个愚蠢的编译器。
在我的机器上,g++ -Wall 已经足够聪明了,会发出一条诊断信息。
int test(...) { if (...) { [计算某些东西并返回]; } else { log_something(...); FATAL_ERROR(); }; }
。如果FATAL_ERROR()
无法返回,则test()
的结尾永远无法到达,但通常编译器无法知道这一点。 - supercatcondition
代表任何表达式。 - n. m.c
文件时才会发生。 - Prince John Wesleymain()
函数不需要显式包含return
语句,可参考Bjarne Stroustrup的网站http://www2.research.att.com/~bs/bs_faq2.html#void-main。 - iammilind#include <iostream>
int foo(){
if(false)
return 5;
}
int main(){
int i = foo();
std::cout << i;
}
警告 C4715:'foo':并非所有控制路径都返回值
foo
函数,就会出现错误,但是如果我在自动生成的_tmain
函数中完全做同样的事情,则不会出现错误;示例。主函数是特殊的(在很多方面都是这样)。 - T.J. Crowdermain
函数没有返回语句。如果省略了它,结果就好像最后有一个 return 0;
一样。 - Xeox
为假且调用者使用返回值时才是错误,这两个情况都不能在编译器中确定,至少在一般情况下是如此。return
并不太困难;Java就是这样做的。然而,在C++中通常不合理要求这样做,因为在C++中,您可以返回无法构造值的用户定义类型(没有默认构造函数等)。因此,程序员可能无法在他或她知道肯定不会执行的分支中提供return
,而编译器也无法确定该分支是否不会执行。int
bar( char ch )
{
switch ( ch & 0xC0 ) {
case 0x00:
case 0x40:
return 0;
case 0x80:
return -1;
case 0xC0:
return 1;
}
}
至少使用通常的选项。尽管很明显这个函数永远不会跌落到底部。
关于这种编程方式,标准规定它会产生未定义行为。
未定义行为是C/C++的乐趣和遗憾,但也是语言设计的基本特征之一,它允许进行许多低级别的优化,使C成为一种“高级汇编语言”(实际上并不是,只是给你一个想法)。
因此,虽然重定向到John的答案,了解GCC使用哪个开关的原因,我想指出一个非常有趣的未定义行为分析及其所有奥秘的文章:每个C程序员都应该知道的未定义行为。它是一篇非常有教育意义的阅读材料。
throw "LOL Y U HERE??"
。由于该行为未定义,因此任何事情都可能发生,抛出异常显然符合“任何事情”。这只是为了测试目的;如果它们在发布版本中被优化掉,我不介意。 - Dennis Zickefoosex
被声明为const bool x = true;
,那么它不是未定义的。 - Bo Persson