从C中的非void函数返回任何内容

时间:2010-07-12 10:44:03

标签: c gcc return warnings

以下代码段中的最佳做法是什么:

int foo(struct data *bar, struct info bla) {
    if (!bar) {
        bla->status = 0;
        return;
    }
    ...
}
事实上,它运作正常。但gcc给我一个警告,我感到很不舒服。


这是实际代码:

static int pop(struct stack **stack, struct info *info) {
        int ret;
        struct stack *tmp;

        if (!*stack) {
                info->error = 0;
                return;
        }

        ret = (*stack)->data;
        tmp = *stack;
        *stack = (*stack)->next;
        free(tmp);

        return ret;
}

8 个答案:

答案 0 :(得分:12)

最佳做法是不要编写类似的代码。如果此时无法返回某种整数,则需要重新设计代码。请注意,写入的函数会向调用代码返回某种值 - 您只是不知道该值是什么。

这种经典的方法是通过指针参数返回值,实际函数返回状态:

int f( int * p ) {
   if ( bad ) {
       return 0;   // fail indicator
   }
   else {
      * p = 42;    // integer return value
      return 1;    // success indicator
   }
}

编辑:在您发布的代码中,您正在操作堆栈。弹出一个空堆栈是我所知道的所有堆栈的未定义行为,所以你可以只返回任何你想要的整数(我会返回0)并记录行为。

答案 1 :(得分:6)

行为未定义,警告是有充分理由的!返回一个值,或将函数更改为void函数。

答案 2 :(得分:1)

假设返回值未用于此特定情况,只需返回0.如果使用返回值,则程序逻辑中存在严重缺陷,需要先修好了。

答案 3 :(得分:0)

如果这是错误,则输入return 0;return -1;,并且您的非错误整数是正号。

答案 4 :(得分:0)

如果您无法返回任何内容,您可能会考虑抛出异常,或者如前所述,重新设计代码。

答案 5 :(得分:0)

int main(void)
{
    printf("hello world\n");
}

返回10. Mac OS X上的bash shell证实了这一点。也就是说,每个int返回函数返回一些东西,对于返回其他类型的函数也应如此。如果您没有明确返回,则会返回您不知道的内容。如果您无法在函数末尾返回某些内容,请尝试返回void以查看它是否破坏了代码。如果它中断,则函数需要更多工作,否则,继续使用void返回类型。

答案 6 :(得分:0)

我会考虑添加第三个参数,实际上它将是“返回值”,而不是返回函数的结果,只返回其状态,例如可以是enum(你可以有“STATUS_OK”,“STATUS_FAIL”,“STATUS_NO_RESULT”等......)。

对于任何使用您的函数且同时提供所需行为的人来说这是可以理解的(即,不返回值意味着不接触第三个参数并返回“STATUS_NO_RESULT”)。

答案 7 :(得分:0)

由于你使用info->error来说明函数是否失败,你可以返回任何你想要的东西,因为调用者应该忽略返回值。因此,您可以使用return -1return 0return MAGIC_NUMBER沉默警告......

通常,函数以“相反的方式”编码:返回值表示函数是否成功。如果所有int返回值都很好,您可以编写该函数以使其返回失败或成功,并且在成功时填充数据。在您的情况下,您的info结构可以包含int data,或者您可以向func添加另一个arg。

这样调用者可以执行类似

的操作
if ( pop(stack, info) == SUCCESS ) {
  // ...
  printf("%d\n", info->data);
} else { /* failure */
  // info->data holds no data, but info->error could be an error code, e.g.
  fprintf(stderr, "can't pop: %s\n", error_msg[info->error]);
}

您案例中的用法不太直观:

data = pop(stack, info);
if (info->error != ERROR) {
  // data is valid
} else {
  // data is garbage and we have to say an error occurred.
}

顺便说一句,你没有将info->error设置为不同的0,所以你的代码可能会被窃听; e.g。

  info->error = 0;
  data = pop(stack, info);

即使确实堆栈正常,也会始终触发错误,因此数据有效。