一、原型定义:void assert( int expression );
assert宏的原型定义在<assert.h>中,其作用是先计算表达式 expression ,如果expression的值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用abort 来终止程序运行。
举例说明:下面的代码中,当i初始化为1的时候,打印出来结果为2,如果初始化为0的时候,就会打印错误信息:Assertion failed。
1 #include<stdio.h> 2 #include<assert.h> 3 void test(void); 4 int main() 5 { 6 test(); 7 return 0; 8 } 9 void test(void) 10 { 11 int i=0; 12 assert(i); 13 i++; 14 printf("%d\n",i); 15 }
二、原型定义使用assert的优点:
方便调试,使代码更稳定、不易于出错。在很多项目中,都通过断言来控制代码是否使用,一般格式如下:
#ifdef USE_FULL_ASSERT void assert_failed(uint8_t* file, uint32_t line) { while (1) { } } #endif
这样当我们用一个宏#define USE_FULL_ASSERT 的时候,该函数就生效了。
此外,携带式经常用到的#if 1/0 #endif也可以看做是断言的一种用法。
三、关闭断言宏#define NDEBUG
头文件assert.h定义的宏受NDEBUG的影响。如果预程序在处理这个头文件时已经定义了NDEBUG,assert宏的内容就定义为空,这意味着assert宏不在起作用。所以,可以在最终发布程序的时候可以使用-DNDEBUG关闭断言功能或者把 #define NDEBUG 加到每个源文件中,但这条语句必须放在#include <assert.h>之前。
举例说明:下面的代码的开头部分我们把#define NDEBUG给注释掉了,这样我们默然启用了断言,后面会打印this is a string,如果我们把开头的注释部分去掉,就关闭了断言功能,后面不会打印this is a string。
1 #include <stdio.h> 2 //#define NDEBUG 3 #include <assert.h> 4 int copy_string(char from[],char to[]) 5 { 6 int i=0; 7 while(to[i++]=from[i]); 8 return 1; 9 } 10 int main() 11 { 12 char str[]="this is a string!"; 13 char dec_str[200]="no"; 14 printf("%s\n",str); 15 assert(copy_string(str,dec_str)); 16 printf("%s\n",dec_str); 17 return 0; 18 }
注意:int copy_string(char from[],char to[]);中的返回值不能为0 ,不然断言也不会执行。