断言(Assert)使用、原理以及注意事项详解

一、assert的作用

assert往往用于程序的测试版本阶段,而通常不用于release版本阶段。其于程序员而言,是起到尽早发现程序错误的作用。

assert() 的用法像是一种"契约式编程",其表达的意思就是,若断言在我的假设条件下为真,则能够正常良好的运作,否则调用中断程序终止运行,其实就相当于一个 if 语句:

if(假设成立)
{
     程序正常运行;
}
else
{
      报错&&终止程序!(避免由程序运行引起更大的错误)  
}

assert本身并非一个函数,而是一个宏,其原型定义在"assert.h"库中【第三部分会详细描述】。

assert 的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行。

使用 assert 的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。

题外话,对于Javascript中,没有定义相应的断言,但是可以通过console.assert('假设条件','错误信息')的方式来起到类似的测试作用;或者根据断言的定义,自己设计一个断言函数,若错误直接throw Error

二、assert的用法以及注意事项

1、重要宏定义:NDEBUG和DEBUG
  • NDEBUG:控制assert是否生效, 在调试结束后#define NDEBUG 来禁用 assert 调用。例如:
#include 
#define NDEBUG 
#include "assert.h"

//相当于NDEBUG对assert起到如下作用
#ifdef NDEBUG
#define assert(x) ((void)0)
#else
...
  • DEBUG:代表在测试阶段,可以这样定义宏以控制assert使用
#define DEBUG   // release 版本注释掉即可,测试版本定义
#ifdef DEBUG
#define ASSERT(f) assert(f)
#else 
#define ASSERT(f) ((void)0)
#endif
2、用法示例以及注意事项
  1. 在函数开始处检验传入参数的合法性
    int resetBufferSize(int nNewSize) 
    { 
    //功能:改变缓冲区大小, 
    //参数:nNewSize 缓冲区新长度 
    //返回值:缓冲区当前长度 
    //说明:保持原信息内容不变 nNewSize<=0表示清除缓冲区 
    assert(nNewSize >= 0); 
    assert(nNewSize <= MAX_BUFFER_SIZE); 
     
    ... 
    }
  2. 每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败
    //不好:有两个条件,不知道出错是由于哪个导致
    assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize); 
    
    //好:一个条件,出错直观
    assert(nOffset >= 0); 
    assert(nOffset+nSize <= m_nInfomationSize); 
  3. 不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题
    //错误:改变了环境,使程序变量自增
    assert(i++ <0 )
    
    //正确
    assert(i < 100)
    i++;

三、assert原理

assert在assert.h中定义的完整代码:

  • 首先我们看到预处理命令 #ifdef NDEBUG 这个 NDEBUG 宏,会在程序编译为release版本时编译器会自动定义 NDEBUG这个宏, 而debug版本不会定义,所以debug时只会执行 #else 里的语句,所以根据以上代码可知,一旦程序为release版本,则assert宏只会被展开为 ((void)0) 。

基本的宏定义知识:在某个宏前面+’#’,则被替换时会在左右加上"",作为字符串。

  • 假设现在非NDEBUG,此时进入执行判断表达式真假,若为假调用中断程序。对关键的定义部分化简得到第二行表达式。
//化简
(void)((!!(expression)) ||(_wassert(_CRT_WIDE(#len>0), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) );

=>(void)( ( !!(expression) ) || ( _wassert( #expression,__FILE__,__LINE__ ) , 0 ) );

运行原理:

1、在debug下传入宏参数,展开为一个或表达式,而release下传入,则只会产生 ((void)0) 
2、根据或表达式的判断结果,如果第一个判断结果为1,则短路,不会再执行后面的语句了;
3、如果第一个判断结果为0,则继续执行下一段语句,下一段语句调用一个函数来中断程序的执行,并打印出相应的信息。
 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Python中的assert断言用于在代码中检查某个条件是否为True,如果不是,则会抛出AssertionError异常。它的语法如下: assert expression [, arguments] 其中,expression是需要检查的条件,如果为False,则会抛出异常。arguments是可的,用于在异常信息中提供更多的信息。 assert断言通常用于在开发和调试过程中,帮助程序员快速发现代码中的错误。它可以用于检查函数的输入和输出是否符合预期,以及检查程序中的逻辑是否正确。但是,在生产环境中,assert断言应该被禁用,因为它可能会导致程序崩溃。 ### 回答2: assert断言是Python中的一种工具,用来确认特定的一个条件是True,如果不是True则会抛出AssertionError异常,使得程序停止运行。 在Python中,assert断言常常用于进行程序的调试和检测。通常的用法是在代码中插入一些assert代码,用于检查程序的正确性。如果assert语句检查到错误,那么程序就会崩溃,并打印出错误信息。 assert语句的语法结构如下: assert expression [, arguments] 其中expression为需要检查的条件表达式,如果为False则会抛出AssertionError异常。arguments是可选的,用于指定异常的描述信息。 assert语句一般放在函数或方法中,用于对输入参数或函数处理结果的检查,以确保程序的正确性。例如: def divide(a, b): assert b != 0, "除数不能为0" return a / b print(divide(10, 0)) 上面的代码中,assert语句用于确保函数中的除数不为0,如果除数为0则会抛出异常。通过使用assert语句,我们可以在程序开发和调试中,快速定位并解决问题,提高代码的可靠性和健壮性。 在Python中,assert语句的使用应遵循以下几点原则: 1. 不应该使用assert语句来检查用户的输入,因为可能会导致安全漏洞。 2. 应该将assert语句用于检查预期的程序状态,例如函数参数和返回结果等。 3. 应该遵循“少用assert,多用单元测试”的原则,通过编写单元测试用例来确保程序的正确性和健壮性。 4. 应该使用合适的异常处理机制来处理assert语句可能抛出的异常,以防止程序崩溃。 ### 回答3: Python中的assert是一种用于判断程序逻辑是否正确的语言结构。当assert后面跟的表达式为假(即False或0)时,程序就会停止运行,同时抛出一个AssertionError的异常,从而提醒程序员在代码中存在问题。 使用assert可以方便地对程序进行调试和检查错误,特别是在开发过程中,assert可以帮助开发人员尽早地发现问题并加以修正。例如,在对输入的参数进行校验时,assert可以用于判断参数是否符合预期的格式和范围,若不符合则收到错误信息。 assert的语法结构为:assert expression, message,其中expression为要进行判断的表达式,message为断言失败时要输出的信息。message是可选的,如果省略,则输出默认的信息“AssertionError”。 assert可以与try和except语句联合使用,来处理断言失败时引起的异常。在try块中使用assert,若断言失败,则会抛出AssertionError异常,进入except块进行处理。这样可以保证程序不会因为一个小问题而崩溃,也可以在程序中加入更多的容错性。 总而言之,assert是Python中一种非常有用的调试工具,它可以帮助开发人员快速定位程序的缺陷,从而更加高效地进行开发和维护。在编写代码时,我们可以充分利用assert这个工具,但也需要注意精度和安全性,避免过多使用assert导致程序出现问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

音仔小瓜皮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值