简体   繁体   English

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

[英]Why there is no compiler error when return statement is not present?

Unlike Java, in C/C++ following is allowed :与 Java 不同,在 C/C++ 中允许以下内容:

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

This often causes crashes and hard to debug problems.这通常会导致崩溃和难以调试的问题。 Why standard doesn't enforce to have final return for non- void functions?为什么标准不强制对非void函数进行最终返回 (Compilers generate error for wrong return value) (编译器为错误的return值生成错误)

Is there any flag in gcc/msvc to enforce this? gcc/msvc 中是否有任何标志来强制执行此操作? (something like -Wunused-result ) (类似于-Wunused-result

Use -Wall flag in gcc .gcc中使用-Wall标志。

 warning: control reaches end of non-void function

EDIT : or more specifically -Wreturn-type .编辑:或更具体地说-Wreturn-type

It is not allowed (undefined behaviour).这是不允许的(未定义的行为)。 However, the standard does not require a diagnostic in this case.但是,在这种情况下,该标准不需要诊断。

The standard doesn't require the last statement to be return because of code like this:由于以下代码,该标准不需要return最后一条语句:

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

This always returns 0, but a dumb compiler cannot see it.这总是返回 0,但愚蠢的编译器看不到它。 Note that the standard does not mandate smart compilers.请注意,该标准不强制要求智能编译器。 A return statement after the while block would be a waste which a dumb compiler would not be able to optimise out. while块之后的return语句将是一种浪费,愚蠢的编译器将无法优化。 The standard does not want to require the programmer to write waste code just to satisfy a dumb compiler.该标准不想要求程序员编写废代码只是为了满足愚蠢的编译器。

g++ -Wall is smart enough to emit a diagnostic on my machine. g++ -Wall 足够聪明,可以在我的机器上发出诊断信息。

My guess: Because sometimes the programmer knows better than the compiler.我的猜测:因为有时程序员比编译器更了解。 With this simple example, it's clear that someting is wrong, but consider a switch of many values, or many checks in general.通过这个简单的示例,很明显有些地方是错误的,但考虑一个切换多个值或多个检查的一般情况。 You, as the coder, know that certain values just will not be passed in to the function, but the compiler doesn't and just hints you, that there might be something wrong.作为编码人员,您知道某些值不会传递给 function,但编译器不会,只是提示您,可能有问题。

#include <iostream>

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

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

Note that even warning level 1 on MSVC gives the following warning:请注意,即使 MSVC 上的警告级别 1 也会发出以下警告:

warning C4715: 'foo': not all control paths return a value警告 C4715:“foo”:并非所有控制路径都返回值

You can convert the warning into an error by using the following compiler options您可以使用以下编译器选项将警告转换为错误

-Wreturn-type -Werror=return-type . -Wreturn-type -Werror=return-type

Check out This link看看这个链接

AFAIR Visual Studio 2008 warns you about "execution path that does not have return value". AFAIR Visual Studio 2008 警告您“没有返回值的执行路径”。 It is allowed in the meaning of that "C++ won't stop you from shooting you in the foot".意思是“C++ 不会阻止你朝你的脚开枪”是允许的。 So you are to think, not the compiler.所以你要思考,而不是编译器。

The obvious answer is: because it's not an error.显而易见的答案是:因为这不是错误。 It's only an error if x is false and if the caller uses the return value, neither of which can necessarily be determined by the compiler, at least in the general case.如果x为 false 并且调用者使用返回值,这只是一个错误,编译器不一定能确定这两者,至少在一般情况下。

In this particular case (returning a pointer), it wouldn't be too difficult to require a return for all paths;在这种特殊情况下(返回一个指针),要求所有路径都return并不难; Java does this. Java 就是这样做的。 In general, however, it's not reasonable in C++ to require this, since in C++, you can return user defined types for which it may be impossible to construct a value (no default constructor, etc.) So we have the situation where the programmer might not be able to provide a return in a branch that he or she knows can't be taken, and the compiler can't determine that the branch can't be taken.然而,一般来说,在 C++ 中要求这个是不合理的,因为在 C++ 中,您可以返回可能无法为其构造值的用户定义类型(没有默认构造函数等)所以我们遇到程序员的情况可能无法在他或她知道不能采用的分支中提供return ,并且编译器无法确定该分支不能采用。

Most compilers will warn in such cases, when it can determine the flow.大多数编译器会在这种情况下发出警告,当它可以确定流程时。 All of the ones I've seen also warn in some cases where it's clearly impossible to fall off the end, however.然而,在某些情况下,我所看到的所有这些也都发出警告,显然不可能从末端掉下来。 (Both g++ and VC++ warn about: (g++ 和 VC++ 都警告:

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

    case 0x80:
        return -1;

    case 0xC0:
        return 1;
    }
}

, at least with the usual options. ,至少使用通常的选项。 Although it's quite clear that this function never falls off the end.)虽然很清楚这个 function 永远不会掉到最后。)

What the standard says about this kind of programming is that it produces undefined behavior .标准对这种编程的说法是它会产生未定义的行为

Undefined behavior is the joy and pity of C/C++, but it is also a fundamental feature of the language design that allows for many of the low-level optimizations that make C a sort of "high level assembler" (it is not, actually, but just to give you an idea).未定义的行为是 C/C++ 的乐趣和遗憾,但它也是语言设计的一个基本特征,允许许多低级优化使 C 成为一种“高级汇编程序”(实际上不是,但只是给你一个想法)。

So, while redirecting to John's answer about the switch to use with GCC, to know "why" the standard does not prevent that, I would point to a very interesting analysis of undefined behavior and all of its misteries: What Every C Programmer Should Know About Undefined Behavior .因此,在重定向到约翰关于与 GCC 一起使用的开关的回答时,要知道“为什么”标准不会阻止这一点,我会指出对未定义行为及其所有谜团的非常有趣的分析: 每个 C 程序员应该知道关于未定义的行为 It makes for a very instructive reading.它是一个非常有启发性的阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM