断言 (程序)
目录
断言(程序)
在计算机编程中,特别是在使用命令式编程范式时,断言是一个谓词(状态空间上的布尔值函数,通常表示为使用程序变量的逻辑命题)连接到程序中的一个点,即 always 应该在代码执行的那个点评估为真。 断言可以帮助程序员阅读代码,帮助编译器编译代码,或者帮助程序检测自己的缺陷。
对于后者,一些程序通过在运行时实际评估谓词来检查断言。 然后,如果它实际上不是真的——断言失败——程序认为自己被破坏并且通常故意崩溃或抛出断言失败异常。
详情
下面的代码包含两个断言,x >; 0和x> 1,并且它们在执行过程中的指示点确实为真:
x = 1;断言 x > 0;x++;断言 x > 1;
程序员可以使用断言来帮助指定程序和推断程序的正确性。 例如,前提条件(置于一段代码开头的断言)决定了程序员期望代码执行的一组状态。 后置条件——放在最后——描述了执行结束时的预期状态。 例如:x> 0 { x++ } x > 1.
上面的例子使用了 C. A. R. Hoare 在他 1969 年的文章中使用的包含断言的符号。 该表示法不能用于现有的主流编程语言。 但是,程序员可以使用其编程语言的注释功能来包含未经检查的断言。 例如,在 C 中:
x = 5;x = x + 1;// {x >; 1}
注释中包含的大括号有助于将注释的这种用法与其他用法区分开来。
库也可以提供断言功能。 例如,在 C 语言中使用支持 C99 的 glibc:
#include int f(void){ int x = 5; x = x + 1; 断言(x > 1);}
一些现代编程语言包括检查断言——在运行时或有时静态检查的语句。 如果断言在运行时评估为 false,则会导致断言失败,这通常会导致执行中止。 这将注意力吸引到检测到逻辑不一致的位置,并且可能比否则会导致的行为更可取。
断言的使用有助于程序员设计、开发和推理程序。
用法
在 Eiffel 等语言中,断言构成了设计过程的一部分; 其他语言,例如 C 和 Java,仅使用它们来检查运行时的假设。 在这两种情况下,它们都可以在运行时检查有效性,但通常也可以被抑制。
契约设计中的断言
断言可以作为一种文档形式:它们可以描述代码在运行前期望找到的状态(其前提条件),以及代码期望在运行结束时产生的状态(后置条件); 他们还可以指定类的不变量。 Eiffel 将此类断言集成到语言中并自动提取它们以记录类。 这构成了合同设计方法的重要组成部分。
这种方法在没有明确支持它的语言中也很有用:在注释中使用断言语句而不是断言的优点是程序可以在每次运行时检查断言; 如果断言不再成立,则可以报告错误。 这可以防止代码与断言不同步。
用于运行时检查的断言
断言可用于验证程序员在程序实现期间所做的假设在程序执行时仍然有效。 例如,考虑以下 Java 代码:
int total = countNumberOfUsers(); if (total % 2 == 0) { // total 为偶数 } else { // total 为奇数且非负 assert total % 2 == 1; }

在 Java 中,% 是取余运算符(取模),在 Java 中,如果它的xxx个操作数是负数,那么结果也可以是负数(与数学中使用的取模不同)。 在这里,程序员假设 total 是非负数,因此除以 2 的余数将始终为 0 或 1。该断言明确了该假设:如果 countNumberOfUsers 确实返回负值,则程序可能存在错误 .
这种技术的一个主要优点是,当错误确实发生时,它会被立即和直接检测到,而不是通过通常模糊的效果来检测。 由于断言失败通常会报告代码位置,因此通常无需进一步调试即可查明错误。
断言有时也会放在执行不应该到达的地方。 例如,在 C、C++ 和 Java 等语言中,断言可以放在 switch 语句的默认子句中。