C++ Assert()断言机制原理以及使用

机器学习以及人工智能的学习需要扎实的数学功底才能走的更远,爬的更高,所以打好数学基础是关键,但无论工作学习都没有充足的时间去拿着书本一个字一个字的去学习了,这里我建议大家找几个比较靠谱入门的机器学习或者人工智能学习平台,一定要系统全面的去学习才能有效果,不要半途而废, 在此推荐一个我看过的小白人工智能入门教程,零基础教程,简单通俗易懂,风趣幽默,由浅及深,点击这里可以直达:人工智能入门基础教程,  关注公众号:木石说(mushiwords) 或者加好友 gy10654 一起加入学习群,共同监督,各大名校学霸相互提供学习资源。

MSDN原文如是说:

Evaluates an expression and, when the result is false, prints a diagnostic message and aborts the program.

(判断一个表达式,如果结果为假,输出诊断消息并中止程序。)

void assert( 
   int expression 
);

 

参数:Expression (including pointers) that evaluates to nonzero or 0.(表达式【包括指针】是非零或零)

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

MSDN示例程序;

// crt_assert.c
// compile with: /c
#include <stdio.h>
#include <assert.h>
#include <string.h>

void analyze_string( char *string );   // Prototype

int main( void )
{
   char  test1[] = "abc", *test2 = NULL, test3[] = "";

   printf ( "Analyzing string '%s'\n", test1 ); fflush( stdout );
   analyze_string( test1 );
   printf ( "Analyzing string '%s'\n", test2 ); fflush( stdout );
   analyze_string( test2 );
   printf ( "Analyzing string '%s'\n", test3 ); fflush( stdout );
   analyze_string( test3 );
}

// Tests a string to see if it is NULL, 
// empty, or longer than 0 characters.
void analyze_string( char * string )
{
   assert( string != NULL );        // Cannot be NULL
   assert( *string != '\0' );       // Cannot be empty
   assert( strlen( string ) > 2 );  // Length must exceed 2
}


输出结果

Analyzing string 'abc'
Analyzing string '(null)'
Assertion failed: string != NULL, file assert.cpp, line 25

abnormal program termination


 

用法总结:

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只有在Debug版本中才有效,如果编译为Release版本则被忽略掉。(在C中,ASSERT是宏而不是函数),使用ASSERT“断言”容易在debug时输出程序错误所在。
   而assert()的功能类似,它是ANSI C标准中规定的函数,它与ASSERT的一个重要区别是可以用在Release版本中。

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

加入#define NDEBUG之后,上文第一个例子输出结果为:

Analyzing string 'abc'
Analyzing string '(null)'
Analyzing string ''

 

在面试中经常用到的一个题目:

已知memcpy的函数为: void* memcpy(void *dest , const void* src , size_t count)其中dest是目的指针,src是源指针。不调用c++/c的memcpy库函数,请编写memcpy。

 

void* memcpy(void *dst, const void *src, size_t count)    
{    
	//安全检查
	assert( (dst != NULL) && (src != NULL) );    

	unsigned char *pdst = (unsigned char *)dst;    
	const unsigned char *psrc = (const unsigned char *)src;    

	//防止内存重复
	assert(!(psrc<=pdst && pdst<psrc+count));    
	assert(!(pdst<=psrc && psrc<pdst+count));    

	while(count--)    
	{    
		*pdst = *psrc;    
		pdst++;    
		psrc++;    
	}    
	return dst;    
}  


 

 

数学基础是通信密码学原理关键,我建议大家找几个比较靠谱入门的机器学习或者人工智能学习平台,在此推荐一个我看过的小白人工智能入门教程,零基础教程,简单通俗易懂,点击这里可以直达:人工智能入门基础教程

 

 

 

 

<think>我们正在讨论HAL库中的断言机制及其使用方法。根据引用[3]和引用[4],HAL库中使用断言机制来检查函数参数的有效性。具体来说,在代码中会看到`assert_param`宏,它用于在开发阶段帮助开发者捕获可能的参数错误。 引用[4]提到,断言机制是通过宏`USE_FULL_ASSERT`来控制的。当定义了这个宏时,`assert_param`会被展开为一个参数检查的语句;如果未定义,则`assert_param`被定义为空,编译器会优化掉,不产生任何代码。 使用步骤: 1. 在开发阶段,为了调试和定位错误,可以在工程中定义宏`USE_FULL_ASSERT`(通常在编译器的预定义宏中设置,或者在头文件中定义)。 2. 在发布版本时,去掉`USE_FULL_ASSERT`宏的定义,以节省系统资源。 集成方法: 在HAL库中,断言机制已经内置在库函数中。我们只需要在开发时启用宏`USE_FULL_ASSERT`即可。例如,在STM32CubeIDE中,可以在项目的属性中设置预定义宏。 示例代码片段(取自引用[3]和引用[4]): 在HAL库的函数中,会看到如下代码: ```c void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) { /* 检查参数 */ assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); /* ... 其他代码 */ } ``` 其中,`IS_GPIO_ALL_INSTANCE`和`IS_GPIO_PIN`是用于检查参数有效性的宏,如果传入的参数不符合要求,断言会触发。在调试环境下,通常会使程序停止在断言失败的地方,方便开发者检查。 注意:断言机制只在开发调试阶段使用,发布时应关闭,以避免因为断言失败导致程序中止。 相关问题: 1. 如何在实际项目中启用HAL库的断言功能? 2. 断言失败时,程序会如何表现? 3. 除了参数检查,HAL库的断言还可以用于哪些情况? 4. 关闭断言后,对程序性能有什么影响?</think>### HAL库断言机制详解 HAL库中的断言机制主要用于开发阶段的参数验证和错误检测。以下是其使用方法和工作原理: #### 1. **断言机制工作原理** - 当启用断言时,`assert_param()`宏会对函数参数进行有效性检查 - 检查逻辑基于预定义的验证宏,例如: ```c assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); // 检查GPIO引脚有效性 assert_param(IS_ADC_ALL_INSTANCE(hadc)); // 检查ADC实例有效性 ``` - 如果参数不符合要求,会触发`assert_failed()`函数并中止程序执行[^3][^4] #### 2. **启用断言的方法** 在工程配置中定义宏`USE_FULL_ASSERT`: 1. **Keil/IAR**: - 项目属性 → C/C++ → 预处理器定义 → 添加`USE_FULL_ASSERT` 2. **STM32CubeIDE**: - 项目属性 → C/C++ → Build → Settings → Tool Settings → MCU Settings - 勾选`USE_FULL_ASSERT`选项 3. **源码定义**(不推荐): ```c #define USE_FULL_ASSERT // 在main.h中添加 ``` #### 3. **断言处理函数实现** 需在`main.c`中自定义错误处理函数: ```c void assert_failed(uint8_t *file, uint32_t line) { /* 用户自定义处理逻辑 */ printf("Assert failed: %s, line %d\n", file, line); while(1); // 死循环防止程序继续运行 } ``` #### 4. **集成注意事项** - **开发阶段**:启用断言快速定位参数错误 - **发布版本**:禁用断言以节省资源(移除`USE_FULL_ASSERT`) - **资源消耗**:启用后增加约5-10%的代码空间占用[^4] - **验证范围**:覆盖外设初始化、时钟配置、中断优先级等关键操作 > ⚠️ 重要提示:断言仅捕获参数错误,不能替代运行时错误检查。实际项目中建议结合硬件看门狗使用[^3]。 #### 5. **典型应用场景** ```c HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart) { /* 参数检查 */ assert_param(IS_UART_INSTANCE(huart->Instance)); assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate)); /* 初始化逻辑... */ } ``` ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值