什么是“断言”?函数?

我一直在学习OpenCV教程,遇到了assert函数;它能做什么?

331024 次浏览

看一看

assert()示例程序在c++ .

许多编译器提供assert() 宏。assert()宏返回TRUE 如果其参数的值为TRUE和 采取某种行动,如果 评估错误的。许多编译器会 的assert()终止程序 失败;其他则抛出异常

assert()的一个强大特性 宏就是预处理器 将其折叠成没有代码,如果 没有定义DEBUG。这是一个伟大的 开发期间的帮助 最终产品没有出货 业绩处罚也不增加 的可执行版本的大小 程序。< / p >

#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语句的消息),如果它的参数被证明为假。它通常在调试期间使用,以使程序在发生意外情况时更明显地失败。

例如:

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));

当你在进行发布(非调试)构建时,你也可以通过定义NDEBUG宏来消除计算assert语句的开销,通常使用编译器开关。由此推论,你的程序从来没有应该依赖assert宏运行。

// 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()并且不能保证执行任何操作,因此断言应该只用于测试开发人员假设的事情,而不是用于测试用户输入的数字而不是字母(这应该通过其他方式处理)。

它是一个函数,如果它计算的值为false,则将停止程序执行。通常它被宏包围,这样在使用发布设置编译时就不会编译到结果二进制文件中。

它被设计用来测试你所做的假设。例如:

void strcpy(char* dest, char* src){
//pointers shouldn't be null
assert(dest!=null);
assert(src!=null);


//copy string
while(*dest++ = *src++);
}

理想的情况是,您可以在程序中犯错误,例如调用带有无效参数的函数,并且在它发生段错误(或未能按预期工作)之前命中断言。

像“抛出异常”和“停止执行”这样的东西可能对大多数编译器是正确的,但不是所有的。(顺便问一下,真的有assert语句抛出异常吗?)

下面是c6x和其他TI编译器使用的assert的一个有趣的、略有不同的含义:在看到某些assert语句时,这些编译器使用该语句中的信息来执行某些优化。邪恶。

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位边界上对齐的,因此编译器可以生成针对这种对齐的特定指令。

断言计算机语句类似于英语中的确保语句。

assert()函数可以诊断程序错误。在C语言中,它在<assert.h>中定义,在c++中,它在<cassert>中定义。它的原型是

void assert(int expression);

参数表达式可以是您想要测试的任何东西——变量或任何C表达式。如果expression的值为TRUE, assert()不执行任何操作。如果表达式的计算值为FALSE, assert()在stderr上显示错误消息并中止程序执行。

如何使用assert()?它最常用于跟踪程序错误(与编译错误不同)。bug不会阻止程序编译,但会导致程序给出不正确的结果或不正确地运行(例如锁定)。例如,你正在编写的财务分析程序可能偶尔会给出错误的答案。您怀疑问题是由变量interest_rate取负值引起的,这是不应该发生的。要检查这一点,请放置声明

assert(利率>= 0); 在程序中使用interest_rate的位置。如果变量变成负数,assert()宏会提醒您。然后,您可以检查相关代码以定位问题的原因

要查看assert()如何工作,请运行下面的示例程序。如果输入非零值,程序将显示该值并正常终止。如果输入0,assert()宏强制异常终止程序。你看到的确切错误消息将取决于你的编译器,但这里有一个典型的例子:

断言失败:x,文件list19_3.c,第13行 注意,为了使assert()工作,您的程序必须在调试模式下编译。有关启用调试模式的信息,请参阅编译器文档(稍后解释)。稍后在发布模式下编译最终版本时,assert()宏将被禁用

 int x;


printf("\nEnter an integer value: ");
scanf("%d", &x);


assert(x >= 0);


printf("You entered %d.\n", x);
return(0);

输入整型值:10

您输入了10。

输入整型值:-1

< p >错误信息: 程序异常终止

您的错误消息可能不同,这取决于您的系统和编译器,但总体思想是相同的。

此外,您还可以使用它来检查动态分配是否成功。

代码示例:

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 a dynamic
// array (size 3) of actual int values
}


assert (p);            // Check the dynamic allocation.

类似于:

if (p == NULL) {
cout << "dynamic allocation failed" << endl;
exit(1);
}

c++ 11 N3337标准草案

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

19.3断言

头文件>,如(表42)所述,提供了一个宏,用于记录c++程序断言 以及禁用断言检查的机制

2内容与标准C库头文件<assert.h>相同。

c99n1256标准草案

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

7.2诊断断言> .h

头文件<assert.h>定义了assert宏,并引用另一个宏NDEBUG,该宏不是由<assert.h>定义的。NDEBUG被定义为宏名 在包含<assert.h>的源文件中,assert宏被简单定义为

 #define assert(ignore) ((void)0)
assert宏根据NDEBUG的当前状态重新定义 <assert.h>包含在内 < p > 2。 assert宏应该作为宏实现,而不是作为实际函数。如果 宏定义被抑制以访问实际函数,行为是 定义。< / p >

7.2.1程序诊断

7.2.1.1 assert宏

剧情简介

1.

#include <assert.h>
void assert(scalar expression);

描述

< p > 2 assert宏将诊断测试放入程序中;它展开为一个空表达式。 当它被执行时,if表达式(它应该有一个标量类型)为假(即, 比较= 0)时,assert宏将写入关于特定调用的信息 失败(包括参数的文本、源文件的名称、源行 的值,以及封闭函数的名称-后者分别是的值 预处理宏__FILE____LINE__和标识符 __func__)在标准错误流上使用实现定义的格式。165年) 然后调用abort函数

返回

< p > 3 assert宏不返回任何值

使用assert()函数而不是普通的if else和printf有三个主要原因

  1. Assert()函数主要用于调试阶段,每次你想测试一个甚至可能不会出现在最终代码中的条件时,用printf语句编写if else是很乏味的。

  2. 在大型软件部署中,assert非常方便,可以让编译器在链接assert()函数的头文件之前使用定义的NDEBUG宏忽略assert语句。

  3. 当您在设计一个函数或一些代码时,想要了解是什么限制了代码的工作,最后包含一个if else来计算它,基本上是在玩假设,Assert()很方便。