【问题标题】:checking values inside functions vs outside?检查函数内部与外部的值?
【发布时间】:2013-10-27 18:13:08
【问题描述】:

我个人总是使用它们检查函数内部的值,但在我们大学,一位老师希望我们始终检查函数外部的值。如果我们要用相同的检查值多次调用函数,我认为在函数之外检查一次值可能是个好主意。但是,如果您忘记检查临界值,它可能会给您带来错误,例如程序中的分段错误。

我已经粘贴了我正在处理的代码。在学校,我们应该检查函数之外的值,但我认为这很疯狂,在这种情况下是浪费时间。主要功能在代码的末尾,您可以在检查 malloc 的返回值(函数外的 init_unsecure 和函数内的 init_secure)或在删除元素之前检查元素是否存在时(函数外的 remove_unsecure 谁重复)时看到差异存在函数中的while循环和函数中的remove_secure)。

你怎么看?检查函数内部的值不是很明显吗?

#include <stdlib.h>

typedef struct  strens
{
  int       v[100];
  int       n;
}       StrEns, *Ens;

// init struct pointer (need to check if return value is not NULL)
Ens init_unsecure()
{
  Ens   e;

  if ((e = malloc(sizeof(StrEns))) != NULL)
    e->n = 0;
  return e;
}

// init struct pointer and check if malloc is not NULL
Ens init_secure()
{
  Ens   e;

  if ((e = malloc(sizeof(StrEns))) == NULL)
    exit(EXIT_FAILURE);
  e->n = 0;
  return e;
}

// insert element
Ens insert(Ens e, int x)
{
  e->v[e->n] = x;
  ++e->n;
  return e;
}

// return if element exists or not
int exists(Ens e, int x)
{
  int i = 0;
  while (i < e->n && e->v[i] != x)
    ++i;
  return (i != e->n);
}

// remove element (need to check if element exists before)
Ens remove_unsecure(Ens e, int x)
{
  --e->n;
  int i = 0;
  while (e->v[i] != x)
    ++i;
  e->v[i] = e->v[e->n];
}

// remove element if exists
Ens remove_secure(Ens e, int x)
{
  --e->n;
  int i = 0;
  while (i < e->n && e->v[i] != x)
    ++i;
  e->v[i] = e->v[e->n];
}

// comparing init_unsecure vs init_secure && remove_unsecure vs remove_secure
int main()
{
  Ens   e1, e2, e3;

  if ((e1 = init_unsecure()) == NULL)
    return EXIT_FAILURE;
  if ((e2 = init_unsecure()) == NULL)
    return EXIT_FAILURE;
  if ((e3 = init_unsecure()) == NULL)
    return EXIT_FAILURE;

  e1 = init_secure();
  e2 = init_secure();
  e3 = init_secure();

  if (exists(e1, 42))
    remove_unsecure(e1, 42);
  if (exists(e2, 42))
    remove_unsecure(e2, 42);
  if (exists(e3, 42))
    remove_unsecure(e3, 42);

  remove_secure(e1, 42);
  remove_secure(e2, 42);
  remove_secure(e3, 42);

  return EXIT_SUCCESS;
}

【问题讨论】:

    标签: c algorithm optimization data-structures


    【解决方案1】:

    C 编程中(仍然)流行的心态是函数的调用者知道他在做什么,因此应该提供有效的参数。不这样做被广泛认为是未定义行为的原因。

    例如,free 不必验证您传递的指针是否已由 malloc 先前返回,因为这会影响性能。只要调用您的函数的代码是正确的并且在预期范围内提供每个参数,即使没有在函数内部进行防御性检查,一切都应该没问题。

    不过,仍然建议在整个代码中使用断言,以便程序员能够尽早发现异常。

    【讨论】:

    • 你说得对,我同意...该工具不使用用户。用户使用该工具。 ;)
    • 因此,考虑到没有错误,您根本不会检查值。只要没有用户输入,你会怎么做?例如,用户给出一个要删除的数字作为参数。如果您不想要无限循环,则必须检查它是否存在或检查 i n 的函数内部。那么,检查内部函数更好,你同意吗?抄送@JoeDF
    • 当涉及到用户输入时,您应该始终对其进行验证。处理输入的代码很可能会验证它,而程序的其他部分被设计为高效且可用,无论是否有用户输入。
    • 好的,但我不明白 if (exists(e1, 42)) remove_unsecure(e1, 42);可以比 remove_secure(e1, 42) 更有效;使用 exists 函数时,您有一个 while 循环,然后 remove_unsecure 也有一个。使用 remove_secure 它可以检查多合一。
    • @BlagovestBuyukliev &baptx :你们都有一些优点,但这一切都取决于你在函数中的内容......举个简单的例子......让我们说strlen(),检查第一个元素为空而不是循环更好..或者例如在c / c ++的标准定义等中还引用了“未定义的行为”,这意味着该函数不检查这是否是有效的输入......所以,我是说,你们都是对的,但这真的取决于你们在做什么。 ;)
    猜你喜欢
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 2013-12-29
    • 2019-11-28
    • 1970-01-01
    • 2019-03-22
    • 2013-04-08
    • 2018-06-12
    相关资源
    最近更新 更多