什么是“断言”function?
我一直在研究OpenCV教程,并遇到了assert
函数; 它有什么作用?
如果它的参数结果是错误的, assert
将终止程序(通常带有引用assert语句的消息)。 在debugging过程中通常会使用,如果发生意外情况,程序会更加明显地失败。
例如:
assert(length >= 0); // die if length is negative.
如果失败,也可以添加更多信息来显示:
assert(length >= 0 && "Whoops, length can't possibly be negative! (didn't we just check 10 lines ago?) Tell jsmith");
或者像这样:
assert(("Length can't possibly be negative! Tell jsmith", length >= 0));
在进行发布(非debugging)构build时,还可以通过定义NDEBUG
macros(通常使用编译器开关)来消除评估assert
语句的开销。 这个推论是你的程序不应该依赖assertmacros运行。
// BAD assert(x++); // GOOD assert(x); x++; // Watch out! Depends on the function: assert(foo()); // Here's a safer way: int ret = foo(); assert(ret);
从调用abort()的程序和不保证做任何事情的组合,断言只应用于testing开发人员假设的东西,而不是用户input数字而不是字母(应该是通过其他方式处理)。
声明计算机声明类似于英语中的声明。
看一眼
assert()示例程序在C ++中
许多编译器提供了一个assert()macros。 如果assert()macros的参数计算结果为TRUE,则返回TRUE,如果计算结果为FALSE,则返回某种行为。 许多编译器会中断一个assert()失败的程序; 别人会抛出一个例外
assert()macros的一个强大特性是,如果DEBUG没有定义,预处理器就会将其折叠为无代码。 在开发过程中有很大帮助,最终产品发货时不会影响性能,也不会增加程序的可执行版本的大小。
例如
#include <stdio.h> #include <assert.h> void analyze (char *, int); int main(void) { char *string = "ABC"; int length = 3; analyze(string, length); printf("The string %s is not null or empty, " "and has length %d \n", string, length); } void analyze(char *string, int length) { assert(string != NULL); /* cannot be NULL */ assert(*string != '\0'); /* cannot be empty */ assert(length > 0); /* must be positive */ } /**************** Output should be similar to ****************** The string ABC is not null or empty, and has length 3
assert()可以诊断程序错误。 它在ASSERT.H中定义,其原型是
void assert(int expression); 参数expression式可以是任何你想testing的variables或者任何Cexpression式。 如果expression式评估为TRUE,则assert()不执行任何操作。 如果expression的计算结果为FALSE,则assert()会在stderr上显示一条错误消息,并中止程序的执行。
你如何使用assert()? 它是最常用来追踪程序错误(与编译错误不同)的。 一个错误不会阻止程序编译,但会导致错误的结果或不正确的运行(例如,locking)。 例如,您正在撰写的财务分析程序可能偶尔会提供不正确的答案。 您怀疑问题是由variablesinterest_rate造成的负值造成的,而这个值永远不会发生。 要检查这个,放置语句
assert(interest_rate> = 0); 在程序中使用interest_rate的位置。 如果variables变成负数,assert()macros会提醒你。 然后,您可以查看相关的代码来找出问题的原因。
要查看assert()是如何工作的,请运行下面的示例程序 。 如果input一个非零值,程序将显示该值并正常终止。 如果input零,assert()macros强制exception程序终止。 你看到的确切的错误信息将取决于你的编译器,但这里是一个典型的例子:
断言失败:x,文件list19_3.c,第13行请注意,为了使assert()工作,您的程序必须以debugging模式编译。 有关启用debugging模式的信息,请参阅您的编译器文档(稍后解释)。 当您稍后在发布模式下编译最终版本时,assert()macros将被禁用。
int x; printf("\nEnter an integer value: "); scanf("%d", &x); assert(x >= 0); printf("You entered %d.\n", x); return(0);
input一个整数值:10
你input了10。
input一个整数值:-1
错误消息:程序exception终止
您的错误信息可能会有所不同,具体取决于您的系统和编译器,但总的想法是一样的。
像“引发exception”和“停止执行”这样的东西对于大多数编译器来说可能是正确的,但是并非如此。 (顺便说一下,声明真的thrwoexception?)
以下是c6x和其他TI编译器使用的断言的一个有趣的略有不同的含义:在看到某些断言语句时,这些编译器使用该语句中的信息来执行某些优化。 邪恶。
C中的示例:
int dot_product(short *x, short *y, short z) { int sum = 0 int i; assert( ( (int)(x) & 0x3 ) == 0 ); assert( ( (int)(y) & 0x3 ) == 0 ); for( i = 0 ; i < z ; ++i ) sum += x[ i ] * y[ i ]; return sum; }
这告诉编译器数组在32位边界上alignment,所以编译器可以为这种alignment生成特定的指令。
如果条件(断言)为假,断言允许您停止执行。
比如(伪码):
Bank myBank = Bank.GetMyStuff(); assert(myBank != NULL); // .. Continue.
如果myBank为NULL,则该函数将停止执行,并产生错误。 这对于使某些可重用的代码接受正确的条件非常有用。
这是一个函数,如果它所评估的值是假的,它将暂停程序执行。 通常它被一个macros包围起来,所以在使用发布设置进行编译时,它不会被编译到生成的二进制文件中。
它被devise用来testing你所做的假设。 例如:
void strcpy(char* dest, char* src){ //pointers shouldn't be null assert(dest!=null); assert(src!=null); //copy string while(*dest++ = *src++); }
你想要的理想是你可以在你的程序中发生错误,比如调用带有无效参数的函数,并且在段错误之前触发断言(或者按照预期工作失败)
C ++ 11 N3337标准草案
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
19.3断言
1(表42)中描述的头文件提供了用于loggingC ++程序断言的macros和用于禁用断言检查的机制。
2内容与标准C库标题相同。
C99 N1256标准草案
JTC1/SC22/WG14/www/docs/n1256.pdf
7.2诊断
1头文件
<assert.h>
定义了断言macros,并引用了另外一个未被<assert.h>
定义的macrosNDEBUG
。 如果将NDEBUG
定义为包含源文件中的macros名称,则assertmacros定义为#define assert(ignore) ((void)0)
每当
<assert.h>
被包含时,assertmacros就根据NDEBUG的当前状态重新定义。2.断言macros应作为一个macros来实现,而不是实际的function。 如果为了访问一个实际的函数而禁止了macros定义,这个行为是不确定的。
7.2.1程序诊断
7.2.1.1断言macros
概要
1。
#include <assert.h> void assert(scalar expression);
描述
2断言macros将诊断testing放入程序中; 它扩大到一个空洞的expression。 当它被执行的时候,如果expression式(它应该有一个标量types)是假的(即,比较等于0),assertmacros写入关于特定调用失败的信息(包括参数的文本,源文件,源代码行号和封装函数的名称(后者分别是预处理macros
__FILE__
和__LINE__
以及标识符__func__
)在实现定义格式中的标准错误stream中的值。 然后它调用中止函数。返回
3断言macros没有返回值。
另外,你可以用它来检查dynamic分配是否成功。
代码示例:
int ** p; p = new int * [5]; // Dynamic `array (size 5) of pointers to int` for (int i = 0; i < 5; ++i) { p[i] = new int[3]; // each i(ptr) is now pointing to dynamic array(size3)of actual int values } assert (p); // Check the dynamic allocation . Similar to: if (p == NULL) { cout << "dynamic allocation failed" << endl; exit(1); }