为什么返回语句不存在时没有编译器错误?

时间:2011-06-07 05:24:02

标签: c++ c return-value language-lawyer compiler-flags

与Java不同,在C / C ++中,允许

int* foo ()
{
  if(x)
    return p;
// what if control reaches here
}

这通常会导致崩溃并且难以调试问题。为什么标准不强制执行非void函数的最终返回? (编译器为错误的return值生成错误)

gcc / msvc中是否有任何标志强制执行此操作? (类似于-Wunused-result

7 个答案:

答案 0 :(得分:12)

-Wall中使用gcc标记。

 warning: control reaches end of non-void function

编辑:或更具体地说是-Wreturn-type

答案 1 :(得分:9)

不允许(未定义的行为)。但是,在这种情况下,标准不需要诊断。

标准不要求最后一个语句为return,因为代码如下:

while (true) {
  if (condition) return 0;
}

这总是返回0,但是一个愚蠢的编译器看不到它。请注意,该标准并未强制要求使用智能编译器。在return块之后的while语句将是一个浪费,而愚蠢的编译器将无法优化。该标准不希望程序员编写废弃代码只是为了满足一个愚蠢的编译器。

g ++ -Wall非常聪明,可以在我的机器上发出诊断信息。

答案 2 :(得分:3)

我的猜测:因为有时程序员比编译器更了解。有了这个简单的例子,显然有些错误,但考虑转换许多值,或者通常进行多次检查。作为编码人员,你知道某些值不会被传递给函数,但是编译器没有,只是提示你,可能存在错误。

#include <iostream>

int foo(){
    if(false)
        return 5;
}

int main(){
    int i = foo();
    std::cout << i;
}

请注意,MSVC上的even warning level 1会发出以下警告:

  

警告C4715:'foo':并非所有控制路径都返回值

答案 3 :(得分:1)

AFAIR Visual Studio 2008警告您“没有返回值的执行路径”。允许的意思是“C ++不会阻止你在脚下射击你”。所以你要思考,而不是编译器。

答案 4 :(得分:1)

显而易见的答案是:因为这不是错误。这只是一个错误 x为false,如果调用者使用返回值,则两者都不是 必须由编译器确定,至少在一般情况下 情况下。

在这种特殊情况下(返回一个指针),它也不会 所有路径都难以return; Java这样做。在 但是,在C ++中要求这样做是不合理的,因为在 C ++,您可以返回可能无法使用的用户定义类型 构造一个值(没有默认构造函数等)所以我们有了 程序员可能无法提供return的情况 在他或她知道不能采取的分支中,编译器不能 确定不能采取分支。

大多数编译器会在这种情况下发出警告,以确定流量。 我所见过的所有人在某些情况下也会发出警告 然而,不可能失败。 (g ++和VC ++都警告说:

int
bar( char ch )
{
    switch ( ch & 0xC0 ) {
    case 0x00:
    case 0x40:
        return 0;

    case 0x80:
        return -1;

    case 0xC0:
        return 1;
    }
}

,至少是通常的选择。虽然这很清楚 功能永远不会结束。)

答案 5 :(得分:1)

您可以使用以下编译器选项将警告转换为错误

-Wreturn-type -Werror=return-type

查看此link

答案 6 :(得分:0)

标准对此类编程的说法是它产生未定义的行为

未定义的行为是C / C ++的乐趣和怜悯,但它也是语言设计的一个基本特征,允许许多低级优化使C成为一种“高级汇编程序”(它是不,实际上,只是为了给你一个想法)。

因此,在重定向到约翰关于转换为与GCC一起使用的答案的过程中,为了知道“为什么”标准并没有阻止这一点,我会指出一个非常有趣的分析未定义的行为及其所有的misteries:{{3 }}。这是一个非常有益的阅读。

相关问题