0

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

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

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;
}
4

3 回答 3

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 行),那么多个返回点就可以了。

于 2013-08-12T00:57:51.187 回答
1

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

请参阅:函数是否应该只有一个 return 语句?

于 2013-08-12T00:57:15.523 回答
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;
}

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

于 2013-08-12T07:04:52.837 回答