试图理解断言的有用性

时间:2014-01-13 05:22:47

标签: c

assert()的用处是什么,当我们也可以使用printf和if-else语句时会告诉用户b是0?

#include <stdio.h>
#include <assert.h>

int main() {
int a, b;

printf("Input two integers to divide\n");
scanf("%d%d", &a, &b);

assert(b != 0);

printf("%d/%d = %.2f\n", a, b, a/(float)b);

return 0;
}

6 个答案:

答案 0 :(得分:3)

人们在这里混淆了两件事。验证运行时和设计时错误。

当用户只输入数字时,如果函数遇到的输入是字母数字,那么它就是运行时错误。您需要以用户友好,优雅的方式向用户提出这个问题;这涉及将错误冒泡到正确的层等等。

虽然您做出了设计时决定。假设您正在设计一个名为unit_vec的函数,该函数涉及将向量的分量除以其长度;此功能应确保不会发生零差错。传递 0 向量会破坏此函数,因为它的长度为 0

你确定你的矢量都不是 0 向量(假设),因此你不希望检查长度的成本是0在发布的代码中if;但是在调试版本中,您可以确保使用assert永远不会遇到这种情况,即您声明(验证)您所做的设计时假设。假如某个函数碰巧传递 0 ,那么在调试版本中你会看到调试中断命中,从而允许你纠正错误的函数。

这是assert仅针对调试版本启用的基本原理,即未设置NDEBUG时。

答案 1 :(得分:2)

断言不会用于通知用户任何事情。断言用于在您的程序中强制执行invariants

在上面的程序中,断言被滥用。 b != 0不是一个不变量。这是在运行时检查的条件,正确的方法是

if (b == 0) {
   sprintf(stderr, "Can't divide by 0\n");
   return -1;
}

这意味着程序将检查用户输入,如果不正确则中止。断言是不合适的,因为,一,它可以使用NDEBUG宏编译出来,在你的情况下,它将改变程序逻辑(如果输入为0,程序将继续使用{{的printf) 1}}})和两个因为断言的目的是assert程序中某个点的条件。

example in the wikipedia article I've linked to为您提供了一个断言是正确使用的地方。当有人试图阅读和理解算法时,它有助于确保程序的正确性并提高可读性。

答案 2 :(得分:0)

在程序中,如果条件b != 0成立,则程序执行将继续,否则终止并显示错误消息,仅printf无法执行此操作。使用if-else也可以,但这不是MACRO。

答案 3 :(得分:0)

断言将停止程序,它标志着一个永远不会发生的情况。

来自Wikipedia

  

执行时,如果表达式为假(即比较等于0),则assert()写入   有关在stderr上失败的调用的信息,然后调用abort()。信息&gt;写给stderr包括:

the source filename (the predefined macro __FILE__)
the source line number (the predefined macro __LINE__)
the source function (the predefined identifier __func__) (added in C99)
the text of expression that evaluated to 0 [1]
  

在Linux上用gcc编译的程序的示例输出:

program: program.c:5: main: Assertion `a != 1' failed.
Abort (core dumped)

答案 4 :(得分:0)

  1. 它会停止程序并防止它出错(除了突然停止)。

  2. 这就像一个烘焙断点;调试器将在其上停止,而无需额外的手动工作来查找printf的行号并设置断点。 (assert仍然可以帮助打印此信息。)

  3. 默认情况下,它定义为以NDEBUG宏为条件,通常设置为反映开发环境中的调试/发布构建开关。这可以防止它降低性能或导致最终用户膨胀。

  4. 请注意,assert并非旨在通知用户任何内容;它只用于调试程序员的输出。

答案 5 :(得分:0)

这不是断言的好用;使用断言验证用户输入对于除您自己的私人用途以外的任何其他内容都是非常残酷的。

这是一个更好的例子 - 这是一个方便的我恰好在踢:

int Random_Integer(int lo, int hi)
{
    int range = hi - lo + 1;
    assert(range < RAND_MAX);
    int max_r = RAND_MAX - (RAND_MAX % range);
    int r;
    while ((r = rand()) > max_r)
        ;
    return (r % range + lo);
}

如果RAND_MAX的值小于请求的整数范围,则此代码不起作用,因此断言强制执行该关键约束。