C 检查函数内部和外部的值?

C 检查函数内部和外部的值?,c,algorithm,optimization,data-structures,C,Algorithm,Optimization,Data Structures,我个人总是使用它们检查函数内部的值,但在我们大学,老师希望我们总是检查函数外部的值。我认为,如果我们要使用相同的检查值多次调用函数,那么最好在函数外部检查一次性值。然而,如果您忘记检查临界值,它可能会给您带来错误,比如程序中的分段错误 我已经粘贴了我正在处理的代码。在学校我们应该检查函数之外的值,但我认为这是疯狂的,在这种情况下是浪费时间。main函数位于代码的末尾,您可以在检查malloc的返回值(函数外部的init_unsecure和函数内部的init_secure)或在移除元素之前检查元素

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

我已经粘贴了我正在处理的代码。在学校我们应该检查函数之外的值,但我认为这是疯狂的,在这种情况下是浪费时间。main函数位于代码的末尾,您可以在检查malloc的返回值(函数外部的init_unsecure和函数内部的init_secure)或在移除元素之前检查元素是否存在时看到差异(删除复制现有函数中while循环的函数外部的\u unsecure,并删除函数内部的\u 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;
}
#包括
类型定义结构强度
{
INTV[100];
int n;
}力量;
//init struct指针(需要检查返回值是否不为NULL)
Ens init_unsecure()
{
Ens e;
如果((e=malloc(sizeof(strengs))!=NULL)
e->n=0;
返回e;
}
//初始化结构指针并检查malloc是否为NULL
Ens init_secure()
{
Ens e;
如果((e=malloc(sizeof(stress)))==NULL)
退出(退出失败);
e->n=0;
返回e;
}
//插入元素
Ens插件(Ens e,int x)
{
e->v[e->n]=x;
++e->n;
返回e;
}
//返回元素是否存在
整数存在(Ens e,int x)
{
int i=0;
而(in&&e->v[i]!=x)
++一,;
返回(i!=e->n);
}
//移除元素(之前需要检查元素是否存在)
Ens移除_不安全(Ens e,int x)
{
--e->n;
int i=0;
而(e->v[i]!=x)
++一,;
e->v[i]=e->v[e->n];
}
//删除元素(如果存在)
Ens移除_固定(Ens e,int x)
{
--e->n;
int i=0;
而(in&&e->v[i]!=x)
++一,;
e->v[i]=e->v[e->n];
}
//比较init_unsecure与init_secure&&remove_unsecure与remove_secure
int main()
{
欧洲标准e1、e2、e3;
if((e1=init_unsecure())==NULL)
返回退出失败;
if((e2=init_unsecure())==NULL)
返回退出失败;
如果((e3=init_unsecure())==NULL)
返回退出失败;
e1=初始安全();
e2=初始安全();
e3=初始安全();
如果(存在(e1,42))
移除不安全的(e1,42);
如果(存在(e2,42))
移除不安全的(e2,42);
如果(存在(e3,42))
移除不安全的(e3,42);
取下_-secure(e1,42);
取下固定的(e2,42);
取下固定装置(e3,42);
返回退出成功;
}
C编程中(仍然)流行的思维方式是,函数的调用方知道自己在做什么,因此应该提供有效的参数。不这样做被广泛认为是未定义行为的原因

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


尽管如此,还是建议在代码中使用断言,以便作为程序员能够尽早捕获异常情况。

你说得对,我同意……工具不使用用户。用户使用工具。;)因此,考虑到没有错误,你根本不会检查值。只要没有用户输入,你会怎么做?例如,用户给出一个数字作为参数删除。如果你不想要一个无限循环,你必须检查它是否存在,或者检查它是否存在于函数in中。那么,检查内部功能更好,你同意吗?cc@joedfw当涉及到用户输入时,您应该始终验证它。处理输入的代码最有可能是验证输入,而程序的其他部分设计为高效和可用,无论是否有用户输入。好的,但我不明白如果(存在(e1,42))删除不安全(e1,42);可以比移除_-secure(e1,42)更有效;当使用exists函数时,您有一个while循环,然后remove\u unsecure也有一个。使用remove_secure,它可以检查多功能一体机。@BlagovestBuyukliev&baptx:你们都有一些优点,但这取决于函数中的内容。。。举个简单的例子。。让我们说strlen(),检查第一个元素是否为null而不是循环更好。。或者,例如,在c/c++等的标准定义中也有对“未定义行为”的引用,这意味着该函数不检查该输入是否有效。。。所以,我可以说,你们都是对的,但这取决于你们在做什么