【问题标题】:How do I make my function "return a value in all control paths"?如何使我的函数“在所有控制路径中返回一个值”?
【发布时间】:2021-02-02 02:30:29
【问题描述】:

我对编程很陌生,我正在尝试组合一个函数:

#include <cs50.h>
#include <stdio.h>
#include <string.h>

string name;

bool check(string word)
{
    for(int i = 0; i >= 9; i++)
    {
        if (strcmp(name, word) == 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

int main(void)
{
    
}

但是当我尝试编译时,我收到错误消息error: non-void function does not return a value in all control paths [-Werror,-Wreturn-type]。这是什么意思,我该如何解决?

【问题讨论】:

    标签: c function cs50


    【解决方案1】:

    要修复警告,请在check 末尾添加return:

    bool
    check(string word)
    {
        for (int i = 0; i >= 9; i++) {
            if (strcmp(name, word) == 0) {
                return true;
            }
            else {
                return false;
            }
        }
    
    // NOTE/FIX: fixes the warning
        return false;
    }
    

    但是,check 函数中的 for 循环什么都不做(它在每次迭代中做同样的事情),所以你不需要循环。

    另外,请注意您从不将name 初始化为任何内容,因此它会出现段错误,因为string 实际上是char *。您需要将其设置为有效的指针值。

    这是一个带有诊断测试的重构版本:

    #include <cs50.h>
    #include <stdio.h>
    #include <string.h>
    
    string name = "hello";
    
    bool
    check(string word)
    {
        bool match;
    
        match = (strcmp(name,word) == 0) ? true : false;
    
        return match;
    }
    
    string testlist[] = {
        "hello", "world", NULL
    };
    
    int
    main(void)
    {
    
        for (string *cur = testlist;  *cur != NULL;  ++cur) {
            bool ok = check(*cur);
            printf("%s: %s\n",*cur,ok ? "match" : "fail");
        }
    
        return 0;
    }
    

    这是程序输出:

    hello: match
    world: fail
    

    你能帮我处理第一段中的代码吗?看起来它最后只会返回 false 吗?

    当然。你是对的。它只是在末尾添加了一个return 语句[with一个值]。

    哎呀。我刚刚注意到您的for 循环将永远执行,甚至一次。那是因为 i 被初始化为 0。但是,循环条件是 i &gt;= 9,在第一次迭代时将是 false。

    事实上,编译器的优化器会检测到这一点并完全省略循环。

    如果您想循环 [出于某种原因] 10 次,正确的 for 循环应该是:

    for (int i = 0; i <= 9; i++)
    

    使用这个更正的循环,添加的return 将永远实际执行。这是因为循环现在保证执行至少一次。

    它将尝试循环 10 次。但是,if 要么是真要么是假,在 either 的情况下,它会从 within 循环中执行 return,所以事情会立即停止。

    执行最终/添加的return 永远不会“退出”循环。

    但是,编译器无法“知道”这一点。

    或者,更重要的是,它仍然应该在底部标记缺少return,即使它确实意识到它不会在实践中执行。

    看到的是for循环执行后,到了函数的底部,对于一个返回一个值的函数,没有 em> return 语句 [with value] 用于该代码路径。

    【讨论】:

    • 感谢您的回答,克雷格 - 给我几分钟来解析您的答案!
    • 你能帮我处理第一段中的代码吗?看起来它最后只会返回 false 吗?
    • 我想我(希望)有足够的能力诊断出问题所在并修复它。非常感谢。
    【解决方案2】:

    您的循环从不执行任何迭代。在for(int i = 0; i &gt;= 9; i++)中,i被初始化为零,然后循环只在i &gt;= 9时执行。这不是真的(零不大于或等于九),所以循环不会执行。程序控制继续到循环之后,您没有更多代码,只有函数结束。因此函数退出时不使用return 语句,因此不返回任何值。因此编译器会警告你。

    如果您将循环更改为for(int i = 0; i &lt;= 9; i++),则循环将执行,并且使用循环内的代码,肯定会执行return 语句。但是,Clang 和 GCC 编译器仍然会发出警告。据推测,他们这样做是因为有一个假设的代码路径,其中循环结束并且函数如上所述退出。这不可能发生,但是两个编译器都无法推断出它,我觉得这有点令人惊讶。由于无法识别没有return 的路径无法执行,因此会发出警告。

    避免警告的一种方法是在函数末尾添加return 语句。

    【讨论】:

    • 您好,埃里克,感谢您的回答。如果我放一个退货声明,例如return false 在函数的末尾,这不是意味着函数在所有情况下都会返回 false,从而违背了循环的目的吗?
    • @BlueKhakis:位于循环后的语句在循环后执行。或者,如果循环中的语句返回,则循环之后的语句根本不会执行。
    • 感谢您的建议,我会回到我的代码再试一次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 2014-11-15
    • 2014-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多