更多退货声明与更多缩进

时间:2013-08-12 00:48:44

标签: c return indentation

以下哪两个代码块总体上更好?

一个返回语句,更多缩进代码:

struct dnode *dllist_push_front(struct dllist *dllist, void *data)
{       
        struct dnode *dnode = malloc(sizeof(struct dnode));
        if (dnode) {
                dnode->data = data;
                dnode->next = dllist->sentinel->next;
                dnode->prev = dlllist->sentinel;
                dnode->next->prev = dnode;
                dllist->sentinel->next = dnode;
                dllist->size++;
        }
        return dnode;
}

,或者

两个返回状态,缩减代码:

struct dnode *dllist_push_front(struct dllist *dllist, void *data)
{
        struct dnode *dnode = malloc (sizeof(struct dnode));
        if (!dnode)
                return NULL;
        dnode->data = data;
        dnode->next = dllist->sentinel->next;
        dnode->prev = dlllist->sentinel;
        dnode->next->prev = dnode;
        dllist->sentinel->next = dnode;
        dllist->size++;
        return dnode;
}

3 个答案:

答案 0 :(得分:3)

你实际上可以走任何一种方式,但我倾向于选择后者,因为它会立即调出“失败”状态。我个人的偏好是在第一个return之后留下一个空行,因为它更多地提到了这个条件(而且我非常喜欢评论):

struct dnode *dllist_push_front(struct dllist *dllist, void *data) {
    // Get new node, exit immediately if not possible.

    struct dnode *dnode = malloc (sizeof (struct dnode));
    if (!dnode) return NULL;

    // Node exists here, populate data and pointers then return it to caller.

    dnode->data = data;
    :
    return dnode;
}

请记住,的多个返回点可能不好,但情况并非总是如此。

你必须记住指南背后的原因以及多个返回点不好的原因是因为它们有时会导致代码难以理解。

如果您可以轻松地看到流程(除非您的编辑器窗口高于13行,否则您可以在两种情况下都可以看到),多个返回点就可以了。

答案 1 :(得分:1)

我会在“快速失败”方面犯错,这意味着如果你遇到一些会破坏你程序的条件,就不要等待超过必要的时间。否则,您的代码可能会开始变成一堆笨拙的嵌套if子句。

请参阅:Should a function have only one return statement?

答案 2 :(得分:0)

为了清晰的流程和调试,每个函数都只有一个退出点。

有条不紊地使用goto使事情变得简单:

#include <stdio.h>
#include <stdlib.h>

...

typedef enum 
{
  Error_Uninitialised = -1,
  Error_Ok = 0,
  Error_1,
  Error_2,
  Error_3,
  Error_4,
  Error_5,
  ...
} ErrorCode_t;

#ifdef DEBUG
#define LOG(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#else
#define LOG(fmt, ...)
#endif

int func(int a, char b, void * p, ...)
{
  LOG("entering: '%s'\n", __func__);

  int result = Error_NoError;

  if (42 == i)
  {
    result = Error_1;
    goto lblExit;
  }

  if ('y' == c)
  {
    result = Error_2;
    goto lblExit;
  }

  if (!p)
  {
    result = Error_3;
    goto lblExit;
  }

  void * ptmp = realloc(p, i);
  if (!ptmp)
  {
    result = Error_4;
    goto lblExt;
  }

  ...

  lblExit:

  LOG("'%s' returns %d\n", __func__, result);

  return result;
}

对于那些限制自己使用goto的人,以下版本可能有所帮助:

int func(int a, char b, void * p, ...)
{
  LOG("entering: '%s'\n", __func__);

  int result = Error_NoError;

  do
  {
    if (42 == i)
    {
      result = Error_1;
      break;
    }

    if ('y' == c)
    {
      result = Error_2;
      break;
    }

    if (!p)
    {
      result = Error_3;
      break;
    }

    void * ptmp = realloc(p, i);
    if (!ptmp)
    {
      result = Error_4;
      break;
    }

    ...

  } while (0);

  LOG("'%s' returns %d\n", __func__, result);

  return result;
}

如果稍后在项目期间,当涉及到优化时,如果真的必要,可以放弃这种方法。