警告:控制可能会达到非空功能的结束

时间:2016-02-16 22:48:13

标签: c recursion

这是一个递归函数,它将二进制数(以整数数组给出)转换为小数。

double binaryToDecimalRecursive(int *binary, int len) {
    if (len == 0) 
        return *binary;
    if (len > 0) {
        return (binary[0]*pow(2, len))+binaryToDecimalRecursive(binary+1, len-1);
    }
}

GCC编译器给我“控件可以达到非空函数的结束”警告。

我应该采取什么措施来防止这种情况?

7 个答案:

答案 0 :(得分:3)

听起来你从你的代码中改变了你的代码是正确的吗?

double binaryToDecimalRecursive(int *binary, int len) {
    if (len == 0) 
        return *binary;
    if (len > 0) {
        return (binary[0]*pow(2, len))+binaryToDecimalRecursive(binary+1, len-1);
    }
    if(len < 0) return -1;
}

编译器无法识别它将始终遵循这些分支中的至少一个。您可以通过几种方式使其更加明确。这是一种应该有效的方法:

double binaryToDecimalRecursive(int *binary, int len) {
    if (len == 0) 
        return *binary;
    else if (len > 0) { // Added an `else` statement
        return (binary[0]*pow(2, len))+binaryToDecimalRecursive(binary+1, len-1);
    }
    else return -1; // Here too
}

答案 1 :(得分:1)

如果len < 0,函数不返回任何内容。 如果条款小于abort(),则应添加len的子句,或者只返回默认值。

答案 2 :(得分:1)

编译器抱怨,因为您使用的是非void函数,它必须返回一个值。在C中,您必须返回一个值。现在,如果len小于零,函数将不会返回一个值,这是不允许的。

幸运的是,有一个简单的解决方法。如果没有len小于零的情况,你可以将它声明为unsigned int - 因为无符号整数值不能小于零,那么你的函数将涵盖所有可能的输入值len。如果len 小于零,则需要abort()或返回错误代码,以便与给出无效输入的函数的调用者进行通信。

答案 3 :(得分:0)

编译器抱怨是因为你使用的是非void函数,并且编译器事先并不知道if(len == 0)和if(len&gt; 0)这两个条件中的任何一个实现。基本上它希望你有一个不依赖于任何条件的默认返回值,所以如果你以某种方式搞砸了你的逻辑并且它 传递两个条件,该计划仍有一些回报。即你总是需要一个不依赖任何条件的回报。

一个好的修复方法可能是if(len&lt; 0){abort()},并取出if(len&gt; 0)以便成为默认条件。

double binaryToDecimalRecursive(int *binary, int len) {
    if (len == 0) {
        return *binary;
    }
    if (len < 0){
    // I assume your program should never logically reach this condition, so this will be good for debugging. It will be more obvious that you reached an unwanted condition than if you returned -1
        abort();
    }
    // since we have specified actions for len <= 0, this is the equivalent of saying len > 0 without letting the compiler complain about it
    return (binary[0]*pow(2, len))+binaryToDecimalRecursive(binary+1, len-1);
}

答案 4 :(得分:0)

根据您在评论中提供的其他详细信息判断问题的正确解决方案是使用无符号整数类型并完全删除if (len > 0)检查

double binaryToDecimalRecursive(const unsigned *binary, unsigned len) {
    return len == 0 ? 
        *binary :
        binary[0] * pow(2, len) + binaryToDecimalRecursive(binary + 1, len - 1);
}

尽可能使用无符号整数类型,仅在必要时使用有符号整数类型。

P.S。为什么在一个地方将binary[0]称为*binary而在另一个地方称为binary[0]?在如此小的功能中,这样的风格混杂是否有理由?

答案 5 :(得分:0)

在做了近40年的这种工作之后,我个人而言 以更简单,更直接的方式做到:

因为我们想要一个int输出,

long BinarytoDecimal(int binary[], int len)
   {
     int i, index;

     long result;

/**/              - I refer to this as the point of demarcation

     result = 0;
     for (i = 0, index = len; i < len; i++, index--)
        {
          result += (long) binary[i] * (long) pow(2,index);
        }

     return(result);
   }

由于很难说,当有人使用递归来实现循环时, 这应该(我强调应该,我认为)给你相同的结果。

答案 6 :(得分:0)

matt95,

认为你可能会感兴趣。我继续尝试使用两组代码 GCC,在windows7上,在cygwin下,他们都给出了相同的结果 相同的输入。当然,最大的区别是我写的代码不能 可能导致“代码到达非空函数结束”错误。

                               Blake Mitchell