本文给出断言的两种实现方法,非原创,出处参考他处。
1. 利用结构体或数组的大小非负特性
/* Force a compilation error if condition is false, but also produce a result
* (of value 0 and type size_t), so it can be used e.g. in a structure
* initializer (or wherever else comma expressions aren't permitted). */
/* Linux calls these BUILD_BUG_ON_ZERO/_NULL, which is rather misleading. */
#define STATIC_ZERO_ASSERT(condition) (sizeof(struct { int:-!(condition); }) )
#define STATIC_NULL_ASSERT(condition) ((void *)STATIC_ZERO_ASSERT(condition) )
/* Force a compilation error if condition is false */
#define STATIC_ASSERT(condition) ((void)STATIC_ZERO_ASSERT(condition))
在上面#define中,struct {int:-!(condition);},当断言的条件为假时,!(condition)为真(>0),-!(condition)<0,因为结构体的位域大小不可能为负值,则在编译时会出错。
比如,我们要保证一个数k<65535,则
STATIC_ASSERT(k < 65535)
2. 调用断言处理函数的方法
将下面的代码放到某个全局头文件中,其中声明了assert_failed函数,
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
extern void assert_failed(uint8_t* file, uint32_t line);
在.c文件中提供assert_failed的实现
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
printf("Wrong parameters value: file %s \
on line %d\r\n", file, line);
/* Infinite loop */
while (1)
{}
}
使用也非常简单,在assert_failed的while(1)死循环处设置断点,
代码中使用
assert_param(k < 65535);
当断言出错,则程序将停在死循环处,并在stdout打印出出错的文件及行数。
参考:TI的STM32F103库函数