assert的用法以及与条件语句的比较

本文详细介绍了assert宏的原型、作用、已放弃使用的缺点、用法总结与注意事项,包括如何在函数开始处检验传入参数的合法性、每个assert只检验一个条件的重要性、避免使用改变环境的语句以及assert和if的比较。此外,还强调了在实际应用中尽量减少使用assert,以优化程序性能。

  assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:

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

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

复制代码
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
int main( void )
{
       FILE *fp;
    
       fp = fopen( "test.txt", "w" );//以可写的方式打开一个文件,如果不存在就创建一个同名文件
       assert( fp );                           //所以这里不会出错
       fclose( fp );
    
       fp = fopen( "noexitfile.txt", "r" );//以只读的方式打开一个文件,如果不存在就打开文件失败
       assert( fp );                           //所以这里出错
       fclose( fp );                           //程序永远都执行不到这里来
       return 0;
}
复制代码

[root@localhost error_process]# gcc badptr.c 
[root@localhost error_process]# ./a.out 
a.out: badptr.c:14: main: Assertion `fp' failed.

  已放弃使用assert()的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。在调试结束后,可以通过在包含#include <assert.h>的语句之前插入 #define NDEBUG 来禁用assert调用,示例代码如下:

#include <stdio.h>
#define NDEBUG
#include <assert.h>


用法总结与注意事项:

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

  这是因为如果出错,比如在执行之前i=100,那么这条语句就不会执行,那么i++这条命令就没有执行。

  正确:

 assert(i < 100);
 i++;

  4)assert和后面的语句应空一行,以形成逻辑和视觉上的一致感。

  5)有的地方,assert不能代替条件过滤。


与条件过滤的比较:

assert是出错了的话,就直接trap或者reset, 而在release的版本中,一般不会希望trap或者reset,所以用if好一些

assert一般是用来检查bug,主要是用来检查致命的非正常的操作(如向PCI设备写东西,但是PCI设备根本就不存在),执行的最终结果是调用abort,即你的进程异常终止,这在软件发布上是致命的,不管怎么说你的程序至少要执行下去啊,别动不动就终止了.
if是常规性的检查,包括参数判断,异常条件等等,判断的结果处理随你,你可以仅仅打印异常信息,可以终止程序.几乎所有assert能干的事,if都可以干.只是有些同学觉得方便就喜欢用assert.
因此,assert尽量少用,有些公司的c编程规范直接规定不能用assert.

### 作用 `assert` 语句在编程中主要用于调试目的,它允许开发者设置条件检查,以确保程序运行时满足某些条件。如果条件不满足,程序会抛出异常并终止执行,从而帮助开发者快速定位错误。`assert` 常用于开发和测试阶段,确保代码逻辑的正确性,而在生产环境中通常会被禁用以提高性能 [^3]。 ### 用法 #### Python 中的 `assert` 在 Python 中,`assert` 语句的基本语法如下: ```python assert condition, message ``` - `condition`:这是一个布尔表达式,如果其值为 `False`,则触发 `AssertionError` 异常。 - `message`(可选):如果提供了该参数,它将在触发异常时作为错误信息输出。 ##### 示例 ```python assert 1 == 1 assert 2 + 2 == 2 * 2 assert len(['my boy', 12]) < 10 assert range(4) == [0, 1, 2, 3] ``` 如果需要添加异常参数,可以这样做: ```python assert 1 + 1 == 3, "assert failed, exit" ``` 当条件不满足时,将输出指定的错误信息 [^1]。 #### Java 中的 `assert` 在 Java 中,`assert` 语句的语法如下: ```java assert condition; assert condition : message; ``` - `condition`:布尔表达式,如果为 `false`,则抛出 `AssertionError`。 - `message`(可选):可以是一个字符串或表达式,用于提供额外的错误信息。 ##### 示例 ```java public class Test { public static void main(String args[]) { assert 1 + 1 == 2; System.out.println("assert1 ok"); assert 1 + 1 == 3 : "assert failed, exit"; System.out.println("assert2 ok"); } } ``` 运行时需要启用断言功能,可以通过命令行参数 `-ea`(或 `--enableassertions`)来启用 [^3]。 #### C/C++ 中的 `assert` 在 C/C++ 中,`assert` 是一个宏,定义在 `<assert.h>`(C)或 `<cassert>`(C++)头文件中。其语法如下: ```c assert(expression); ``` - `expression`:一个布尔表达式,如果其值为 `false`,则程序会输出错误信息并终止。 ##### 示例 ```c #include <assert.h> #include <stdio.h> int main() { int a = 1; int b = 2; assert(a < b); a += b; printf("%d\n", a); return 0; } ``` 如果 `assert` 的条件不满足,程序会向 `stderr` 输出错误信息并调用 `abort()` 终止执行 [^4]。 ### 注意事项 - `assert` 应该用于检查不应该发生的条件,而不是处理预期的错误情况。例如,不应该用 `assert` 来检查用户输入的有效性,而应该用于检查程序内部逻辑的正确性。 - `assert` 的条件表达式不应该包含副作用,例如函数调用、变量赋值或修改变量的操作符(如 `++`)。因为 `assert` 在发布版本中可能会被禁用,这些副作用可能不会执行 [^2]。 - 在生产环境中,`assert` 通常会被禁用,因此不应该依赖 `assert` 来处理关键的错误检查逻辑。 ### 总结 `assert` 是一种非常有用的调试工具,可以帮助开发者在早期发现和修复程序中的逻辑错误。然而,它不应该被用于处理运行时错误或用户输入验证,因为这些错误应该在程序中被正确处理,而不是通过断言来捕获。合理使用 `assert` 可以提高代码的可读性和健壮性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值