【问题标题】:Cannot understand error: "warning: control reaches end of non-void function [-Wreturn-type]"无法理解错误:“警告:控制到达非 void 函数的结尾 [-Wreturn-type]”
【发布时间】:2021-11-07 22:15:59
【问题描述】:

我最近一直在学习 c++。当我尝试运行以下几行时...

#include <iostream>

short a = 0;
short b = 1;
short c, i;

void Fibonacci(){
    std::cout << a;
    std::cout << b;
    while (a <= 100){
        c = a + b;
        a = b;
        b = c;
        std::cout << c;
    }
}

int prime_number(short a){
    if (a == 1){
        std::cout << "It's a prime number\n";
    } else{
        for (i = 2; i < a; i++){
            if ((a%i) == 0){
                std::cout << "It's a prime number\n";
                std::cout << "The given number is divisible by " << i << "\n";
                return 0;    
            }
        }
        std::cout << "It's not an prime number";
    }
}

int main(){
    short user_input;
    std::cout << "Press 1 for Fibonacci and 2 for prime number";
    std::cin >> user_input;

    if (user_input == 1){
        Fibonacci();
    }
    if (user_input == 2){
        std::cout << "Type the number to check whether it's prime";
        std::cin >> a ;
        prime_number(a);
    }
}

...我收到一条错误消息:

In function ‘int prime_number(short int)’:
Function.cpp:37:1: warning: control reaches end of non-void function [-Wreturn-type]
   37 | }

我在各种平台上搜索了答案,但我无法理解这里到底发生了什么。这是一个错误,因为编译器无法找到函数是否有结束。有人可以帮我理解错误并解决它吗?

【问题讨论】:

  • 现在我可以清楚地理解警告了。感谢您的帮助
  • 没问题。一般来说,stackoverflow 的设计初衷并不是对初学者友好——至少在发布新问题时是这样。它旨在成为独特问题及其答案的存储库 - 并且(很好)所有初学者问题都已经被问过。我不确定哪个网站最适合初学者,但是当您仍在学习基础知识时,我只会在这里发布一个问题作为最后的手段。一开始可能会很艰难——希望你有朋友/老师可以帮助你;否则,也许试试 Quora?祝你好运。 =)

标签: c++ compiler-errors return compiler-warnings


【解决方案1】:

警告不是错误。当您编译程序并且只收到警告(即没有错误)时,这意味着您的程序已成功编译(已生成可执行文件)。当您遇到错误时,这意味着编译已中止(因此没有可执行的输出 - 如果您已经有一个,则不会更新)。

警告您,当整数输入为 1 时,您没有指定 return — 这是无效的。此外,如果它不是1,那么else 语句仍然不能保证returned 值:

for (i = 2; i < a; i++){
    if ((a%i) == 0){
        std::cout << "it's a prime number\n";
        std::cout << "The given number is divisible by " << i << "\n";
        return 0;
    }
}

编译器无法知道return 0 将始终在此处执行 - 即使可以,编译器也并非旨在始终理解代码的逻辑。即使知道你的逻辑,return 0 也只会在 a 大于 2 且非素数时执行。

可以通过将return 语句放在两个if 语句中,甚至放在函数末尾来解决此问题。但是请注意,您从不使用返回值?这意味着您的prime_number() 函数应该是void prime_number(),那么您根本不需要返回值,并且可以在循环中使用break; - 或者如果您愿意,可以使用return;(这里是an example 如何来解决这个特定问题 - 不过还有其他错误,如下所述)。

这可能会让初学者感到困惑:为什么当函数int main() 不包含返回值时它不警告你?这是因为main特殊:如果没有给出返回值,则暗示return 0

这里可能会让您感到困惑的另一件事是,如果您曾经使用标志-Werror 进行编译。如果你这样做了,那么原始代码会给你一个错误,因为Werror 标志会将所有警告变成错误(迫使程序员注意警告)。

您的代码逻辑不正确 - 实际上恰恰相反:1 被定义为不是质数(这是因为我们从 unique prime decomposition,所以数学家选择排除 1 作为素数)。此外,((a%i) == 0) 表示当a 除以i 时,它有0 余数,即。 i 除以a,所以a 不是素数。

最后,避免使用global variables。保留所有变量 local 以便代码的逻辑更简单(更易于阅读/不易出错)。

Here's an example of how you could rewrite your code 解决了以上所有问题。

【讨论】:

    【解决方案2】:

    正如 cmets 中的 Elliott 所说,您收到的警告根本不会影响您的程序。建议你返回一些东西,因为你的函数的返回类型是整数。

    以下是消除警告的简单方法。 :)

    旧代码:

    if (a == 1)
    {
        std::cout << "Its a prime number\n";
    }
    

    没有警告的新代码:

    if (a == 1)
    {
        std::cout << "Its a prime number\n";
        return 0;
    }
    

    【讨论】:

    • “您收到的警告根本不会影响您的程序”-这是不正确的,请参阅godbolt.org/z/MGqKafE5e-您能找出最终的“给定数字可被某物整除”的位置吗?是从哪里来的?
    • (前面的评论是-Werror=return-typecampain给你带来的)
    • @dratenik,记录在案:我在这里被引述说,但那不是我的话。我只是指出“错误”消息实际上是一个警告。不错的演示代码,顺便说一句。
    猜你喜欢
    • 2013-04-29
    • 1970-01-01
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多