C++ 当返回语句不存在时,为什么没有编译器错误?
与Java不同,在C/C++中,允许执行以下操作:C++ 当返回语句不存在时,为什么没有编译器错误?,c++,c,return-value,language-lawyer,compiler-flags,C++,C,Return Value,Language Lawyer,Compiler Flags,与Java不同,在C/C++中,允许执行以下操作: int* foo () { if(x) return p; // what if control reaches here } 这通常会导致崩溃和难以调试的问题。为什么标准不强制要求非无效函数具有最终返回?(编译器为错误的返回值生成错误) gcc/msvc中是否有任何标志强制执行此操作?(类似于-Wunused result)AFAIR Visual Studio 2008警告您“执行路径没有返回值”。这是允许的,意思是“C++不
int* foo ()
{
if(x)
return p;
// what if control reaches here
}
这通常会导致崩溃和难以调试的问题。为什么标准不强制要求非无效函数具有最终返回?(编译器为错误的返回值生成错误)
gcc/msvc中是否有任何标志强制执行此操作?(类似于-Wunused result
)AFAIR Visual Studio 2008警告您“执行路径没有返回值”。这是允许的,意思是“C++不会阻止你射中你的脚”。因此,您应该思考,而不是编译器。在gcc
中使用-Wall
标志
warning: control reaches end of non-void function
编辑:或者更具体地说是-Wreturn类型
我的猜测:因为有时程序员比编译器知道得更好。有了这个简单的例子,很明显,有些事情是错误的,但是考虑到许多价值的转换,或者一般的许多检查。作为编码人员,您知道某些值不会传递给函数,但编译器不会,只是提示您可能有问题
#include <iostream>
int foo(){
if(false)
return 5;
}
int main(){
int i = foo();
std::cout << i;
}
#包括
int foo(){
if(false)
返回5;
}
int main(){
inti=foo();
std::cout这是不允许的(未定义的行为)。但是,在这种情况下,标准不要求诊断
标准不要求最后一条语句为return
,因为代码如下:
while (true) {
if (condition) return 0;
}
这总是返回0,但哑编译器看不到它。请注意,该标准并不强制要求智能编译器。在while
块之后的return
语句将是一种浪费,哑编译器无法对其进行优化。该标准不希望要求程序员编写浪费代码只是为了满足愚蠢的编译器
g++-Wall足够聪明,可以在我的机器上发出诊断信号。显而易见的答案是:因为这不是一个错误。如果
x
为false,并且如果调用者使用返回值,则两者都不是
必须由编译器确定,至少在一般情况下
案例
在这种特殊情况下(返回指针),它不会太复杂
很难要求所有路径都返回;Java就是这样做的
但是,一般来说,C++中不需要这样做,因为
C++,您可以返回用户定义的类型,因为这些类型可能不可能
构造一个值(没有默认构造函数等),这样我们就有了
程序员可能无法提供返回的情况
在一个他或她知道不能被接受的分支中,编译器也不能
确定无法执行分支
在这种情况下,当编译器能够确定流时,大多数编译器都会发出警告。
我看到的所有这些都会在某些情况下发出警告,在这些情况下
但是,不可能从末尾掉下来。(g++和VC++都警告:
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一起使用的交换机的回答时,要知道“为什么”该标准并没有阻止这一点,我想指出对未定义行为及其所有错误的一个非常有趣的分析:。它提供了一个非常有启发性的阅读。您可以使用以下编译器选项将警告转换为错误
-Wreturn type-Werror=返回类型
查看此“请注意,即使MSVC上的警告级别为1,也会发出以下警告:”这很有趣。我甚至在VS 2005的第4级中也没有得到这个警告。@t.J:根据MSDN,2005在第1级也应该发出这个警告。请参阅我添加的链接。@Xeo:很有意思。如果我添加了一个类似于你的foo
函数,我会得到错误,但如果我在自动生成的\tmain
函数中执行完全相同的操作,则不会得到错误。主功能是特殊的(如在许多事情中)。像这样的控制流警告通常只有在Optimizer运行并进行分析时才会发出。因此它们通常仅为零售。@example:这是因为标准特别允许main
没有返回语句。如果省略它,结果就好像最后是return 0;
。IIRC gcc仅诊断当打开优化时,它会被忽略,因为它使用控制流分析对其进行诊断,而不进行优化时,它不会运行。@T.j.Crowder:对于C++,没有返回类型的函数总是会生成诊断消息,即使指定了-Wno返回类型。唯一的例外是在系统头中定义的main和函数
-从gcc-man
pageinterest中,如果我在main
中执行,gcc不会使用-Wall
检测到它,而是在argc
上进行分支。但是如果我添加了一个单独的函数并在其中执行,它确实会检测到它。main
似乎是一个特例(因为它在很多方面都是这样).Edit:@John:Overlapping comments.:-@T.Jmain()
不需要包含显式的返回值;从Bjarne Stroustrup网站上可以看到,它是由标准定义的,在下面的take-away消息中检查Shafik的答案是:如果您想要这些检查,请在gcc上使用-Wall
,并设置高警告级别(3或4)在Visual Studio中。我一直希望有一个编译器标志,该标志将导致所有函数的末尾都有抛出“LOL Y U HERE??”
。该行为未定义,因此任何情况都可能发生,抛出异常肯定符合任何条件。仅供验证