在调用已知的函数之前检查参数以检查参数本身

时间:2016-03-17 15:00:14

标签: c function styles

这是代码风格和传统的问题,我想,但问题如下。

假设我们有一个检查参数的函数,例如:

int do_something(int * arr) {
    if (arr == NULL) {
        printf("arr is NULL\n");
        return -1;
    }
    ...

现在我们将使用它。 问题是:我们应该检查一下我们要传递给它的论点吗?无论如何它会检查它。

这个例子相当简单,现实生活场景可能要困难得多,有更多的参数(和更复杂的检查)以及调用函数带来的更多额外开销 - 如果这是某种IPC。

更一般的问题是:关于这种情况的常见指导方针和做法是什么?

2 个答案:

答案 0 :(得分:2)

这将基于个人经验和偏见。无论如何,这就是:

  1. 如果do_something属于某个库,并且作为可以直接调用的函数向库的用户公开,则最好进行必要的所有检查以确保{{1}很健壮。

  2. 如果它是库中的内部函数,最好还是进行必要的检查以确保do_something是健壮的。我做出的唯一例外是,如果程序/库的性能受到支票的不利影响,我会做出检查。

  3. 如果它是您自己的应用程序中的一个函数,最好还是必须进行所有必要的检查,以确保do_something是健壮的。我做出的唯一例外是,如果程序/库的性能受到支票的不利影响,我会做出检查。

答案 1 :(得分:0)

如果将该功能记录为检查参数,则在没有检查的情况下调用它。例如,free()被明确记录为接受NULL作为参数,因此编写过于常见的内容没有意义

if(p != NULL)
  free(p);

它使您的代码混乱,没有任何好处。避免不必要的呼叫的好处通常在噪声中完全消除。

当然,您必须检查函数的返回值。

如果您是函数的实现者,无论是库函数还是本地帮助函数,甚至可以在某些编译器上注释函数的特定契约。

例如,如果您的函数不接受NULL指针,则可以在函数声明中设置(在gcc上)__attribute__((nonnull))

如果您声明例如:

int do_something(int * arr) __attribute__((nonnull (1)));

你会知道你不能用NULL来调用函数(编译器甚至会在它知道你的情况下发出警告)。但要小心,这个属性可能会让人感到惊讶。如果你像我一样声明它并且你仍然会像在示例中那样检查参数,那么你会发现优化器完全从对象代码中删除了检查。