这可能是一个巨大的新手问题,但我对C和使用'assert'相对陌生。
假设我正在构建一个大型程序,并且有一个void函数test(),它接受一个数组并对该数组执行一些操作。
现在,当我构建这个程序时,我要确保所有函数的输入都是有效的,所以我要确保传递给test()的数组是有效的(也就是说不是null)。
我可以这样写:
if (array == NULL) return;
然而,当我在测试时,它只是返回,很难知道我的方法是否成功地操作了我的数组,除非我检查数组本身。在这种情况下添加断言以确保我自己的调试目的是正常的做法吗?我听说assert不是为生产代码编译的,所以assert只会帮助我,程序员,测试和调试。同时使用if语句和assert似乎有点奇怪,但我不明白if语句如何能让我快速知道测试方法是否成功,我也不明白assert如何能成为产品代码的有效检查。看来他们两个都是需要的?
如果你的函数的契约是它需要一个有效的指针,最好的行为是在传递一个空指针或其他无效指针时大声崩溃。一般来说,您无法测试指针的有效性,但对于空指针,在大多数系统上解引用它们都会崩溃。assert
将是记录这一点并确保崩溃(除非定义了NDEBUG
)的适当方式,以帮助诊断使用错误。
将函数更改为返回错误状态是而不是一个好主意。它使接口变得复杂,并且直到以后才会注意到契约违反(或者如果调用者不检查返回值,则根本不会注意到)。
你已经有了基本的想法。
断言用于确保某些条件永远不会发生。如果调用a可以为NULL的函数无效,则使用您指定的断言(assert(a != NULL))。
因此,测试if (a == NULL)是没有意义的。断言表示您认为此操作无效。如果您已经用断言对代码进行了大量测试,那么您已经"证明"(至少这是想法)您永远不会使用NULL调用函数。但是,如果根据设计,您希望函数在a为null时优雅地忽略它,并且什么都不做,那么测试更合适。而assert则不是,因为如果您打算为某些目的调用函数时带null,则不需要通过让调试模式触发断点来通知发生这种情况。
也就是说,把两者结合起来没有什么意义。
更"高级"的用法可以检查其他值的有效性。假设我有一些处理位图的类,并且位图由类"拥有",可以适当地动态分配和删除。如果我要调用类中对位图执行操作的任何函数,我必须知道它永远不会为NULL。assert适合用于测试存储位图数据的成员指针,以确保当指针为空时不会调用这些函数。
这是使用断言的关键。您试图证明在调试期间不会出现这种情况。这是基本概念。当您正在努力解决这样一种可能性,即对于这样一个值为null是有效的,并且仍然可以优雅地操作时,您可能会发现断言和测试的组合是合理的。也就是说,如果代码的其他用户碰巧在值为null时进行调用,您希望避免崩溃,但如果它碰巧为null,生产代码中仍然不会崩溃。
有时这是你不想接受的性能影响,所以你触发断言,这样你代码的消费者就知道他们正在做一些你声明不应该做的事情。