17

与 Java 不同,在 C/C++ 中允许以下内容:

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

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

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

4

7 回答 7

13

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

该标准不要求最后一条语句是return因为这样的代码:

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

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

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

于 2011-06-07T06:08:50.163 回答
13

-Wallgcc. _

 warning: control reaches end of non-void function

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

于 2011-06-07T05:29:40.500 回答
3

我的猜测:因为有时程序员比编译器更了解。通过这个简单的示例,很明显有些地方是错误的,但考虑一个切换多个值或多个检查的一般情况。作为编码人员,您知道某些值不会传递给函数,但编译器不会,只是提示您,可能有问题。

#include <iostream>

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

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

请注意,即使 MSVC 上的警告级别 1 也会发出以下警告:

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

于 2011-06-07T05:30:34.130 回答
2

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

-Wreturn-type -Werror=return-type.

看看这个链接

于 2018-07-26T13:36:02.947 回答
1

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

于 2011-06-07T05:26:51.060 回答
1

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

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

大多数编译器会在这种情况下发出警告,当它可以确定流程时。然而,在某些情况下,我所看到的所有这些也都发出警告,显然不可能从末端掉下来。(g++ 和 VC++ 都警告:

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

    case 0x80:
        return -1;

    case 0xC0:
        return 1;
    }
}

,至少使用通常的选项。虽然很明显,这个功能永远不会落到最后。)

于 2011-06-07T08:11:23.037 回答
0

标准对这种编程的说法是它会产生未定义的行为

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

因此,在重定向到约翰关于使用 GCC 的开关的回答时,要知道“为什么”标准不会阻止这一点,我会指出对未定义行为及其所有谜团的非常有趣的分析:每个 C 程序员应该知道的关于未定义的行为。它是一个非常有启发性的阅读。

于 2011-06-07T08:21:02.207 回答