c语言断言函数
‘壹’ c语言中output()是什么意思
output()不是C语言中的标准函数。
标准函数,是具有常用功能的函数。在程序设计中,常将一些常用的功能模块编写成的函数放在函数库中供公共选用,一般称为标准函数。程序是由若干个程序模块组成的,高级语言中有子程序这个概念,子程序的功能由函数来实现的。
C++标准函数库为C++程序员们提供了一个可扩展的基础性框架。我们从中可以获得极大的便利,同时也可以通过继承现有类,自己编制符合接口规范的容器、算法、迭代子等方式对之进行扩展。
(1)c语言断言函数扩展阅读:
分类
语言支持
属于language support部分,包含了一些标准类型的定义以及其他特性的定义,这些内容,被用于标准库的其他地方或是具体的应用程序中。
诊断
属于diagnostics部分,提供了用于程序诊断和报错的功能,包含了异常处理(exception handling),断言(assertions),错误代码(error number codes)三种方式。
通用工具
属于general utilities部分,这部分内容为C++标准库的其他部分提供支持,当然你也可以在自己的程序中调用相应功能。比如:动态内存管理工具,日期/时间处理工具。记住,这里的内容也已经被泛化了(即采用了模板机制)。
‘贰’ assert问题,C语言
#ifdef __cplusplus
extern "C" { /*如果定义了cplusplus标识符就加个括号,表示是一个外部的C函数*/
#endif
#undef assert /*取消定义assert标识符*/
#ifdef NDEBUG /*如果定义NDEBUG标识符,就启用下面的语句*/
#define assert(exp) ((void) 0) /*用(void) 0来替换assert函数定义,实际是取消assert函数功能,因为void 0不会生成任何语句*/
#else /*否则的话*/
void CVIANSI _assert(char *, char *, int); /*引入系统函数_assert的定义*/
#define assert(exp) ((exp) ? (void) 0 : _assert(#exp, __FILE__, __LINE__))
/*用 ((exp) ? (void) 0 : _assert(#exp, __FILE__, __LINE__))替换assert(exp)函数定义*/
/*替换后作用是如果exp为真,则执行(void) 0不生成任何语句,如果为假,则执行_assert语句*/
/*_FILE_,_LINE_是编译器常数,编译器在这一句中会将当前源程序的行数和文件名当做函数的参数放到语句中去,然后再编译这个语句*/
#endif
#ifdef __cplusplus
}
#endif
#endif /* _ASSERT_H_ */
‘叁’ ASSERT在C语言中有什么作用
所有的assert都是断言,意思是程序运行到此处时,assert()内的表达式必须返回真,否则程序会抛出错误并停止运行。
在debug编译模式时才产生代码,在release编译时,assert()会直接被忽略。
‘肆’ C语言中assert断言的用法
assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行。
库函数: assert.h
原型定义: void assert( int expression );
assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。例程:
#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不能代替条件过滤
‘伍’ 关于C语言中assert等语法在嵌入式应用当中的含义
assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
意思是:IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)这个判断条件必须为真,否则程序就会进入死循环。
一般assert用来判断必须为真的一些条件,防止程序出现意外错误。
例如:
assert(汽车有4个轮子)//这个是必须成立的条件
开汽车
‘陆’ C语言中用ASSERT调试的八大技巧
技巧1:记住ASSERT的定义
对许多开发人员来说,断言是一个令人困惑的话题,因为它们的许多使用方式与其设计初衷背道而驰。我见到的最清晰的断言定义是这样的:
“断言是在程序某个特定点的一个布尔表达式,除非程序中有缺陷(Bug),否则它的值将为真。”
想要理解上述断言定义的开发人员应该留意下面三个要点:
·断言会评估一个表达式是真还是假
·断言是在代码中的某个点对系统状态的一种假设
·断言会验证系统假设,如果不为真,就表明代码中有一个缺陷
技巧2:使用ASSERT验证函数的先决条件
断言非常适合契约式设计环境,在这种环境中,开发人员非常清晰地定义了某个函数的先决条件。断言可以用来检查该函数的输入是否满足先决条件。就拿图1所示的代码片段为例:
图1:函数的先决条件
函数的STate输入应该在定义的系统状态范围内。如果State不是有效的状态值,那么它就不是错误,而是缺陷!断言可以用来验证State是有效的假设,如图2所示:
图2:对函数先决条件应用断言
在State不小于最大值的事件中,断言表达式将被评估为假,程序于是将停止执行。停止程序执行可以让开发人员很容易马上看到哪里的代码出错,而不是过段时间以后才知道。
技巧3:使用ASSERT验证函数的后置条件
断言也能用来验证契约式设计环境中对某个函数输出的假设。例如,如果前面定义的System_StateSet函数返回SystemState变量,开发人员可以预计它也在期望的范围之内。断言可以用来对缺陷进行监视,如图3所示。
图3:对函数后置条件应用断言
开发人员在查看上述代码后可能会感到这些检查毫无意义。刚刚才设置好的SystemState怎么就会出现大于SYSTEM_STATE_MAX的值呢?答案是这确实不应该出现,然而有时候会莫名其妙地发生改变,也许是通过中断或并行线程,此时断言可以立即标志出这个缺陷。
技巧4:不要把ASSERT用于错误处理
在记住断言定义之后,开发人员应该切记:断言是用于检测缺陷的,不能用于错误处理。错误处理是设计用于响应错误的用户输入和意外的事件顺序的软件。错误在系统中预料是会发生的,但仅仅是因为有无效的输入而并不意味着代码中有缺陷。错误处理应该与缺陷寻找分开来。错误使用断言的一个典型例子是,在试图打开一个文件用于读取时去检查文件的指针,如图4所示。
图4:ASSERT的不当使用
读者可以清楚地看到,试图打开文件的结果与文件系统的状态和用户数据有关,而与代码中的缺陷一点关系也没有。开发人员应该编写错误处理程序,而不是用断言,以便在文件不存在时,错误处理程序可以用一些默认可用数据来创建它,以便后续代码继续操作。
技巧5:ASSERT仅对开发有意义,不能用于生产
开发ASSERT宏的原始意图是在开发过程中启用它,在后面生产时要禁用。可以用NDEBUG宏激活和禁用ASSERT。正确实施的断言在被禁用后应该对嵌入式系统基本没有影响。
问题是,如果测试是在断言启用的情况下进行的(为了捕捉任何缺陷,应该这样做),那么现在禁用断言将导致交付的产品与测试的产品处于不同的状态。断言确实会占用一些代码空间,但更重要的是,它们需要占用少量的时钟周期来评估它们的布尔表达式。禁用ASSERT可能对具有有限资源的裸机系统的执行时序产生很大影响,从而导致在生产系统中产生新的缺陷。开发团队需要判断是否值得冒关闭断言的.风险。
一种替代方案是保留断言在激活状态,而将它们的输出重定向到一个系统日志。这样可以确保任何挥之不去的缺陷很容易被识别,而且能避免中止系统的运行,而中止系统可不是明智之举。
技巧6:不允许断言有副作用
ASSERT的默认实现允许开发人员包含一段可执行代码作为布尔表达式的一部分。举例来说,一个状态变量可以被实现为表达式的一部分并传递给ASSERT。但如果传递给ASSERT的表达式有副作用,也就是说,它会改变嵌入式系统的状态,那么禁用断言将改变系统的行为。开发人员应该确保他们的表达式没有副作用,否则他们需要冒险在系统中增加只针对产品代码唤醒的休眠时间缺陷。
技巧7:断言应该占代码的1%至3%
每个开发人员对于代码库(Code Base)中应该有多少个断言都有自己的主见。大家一致同意的一个数字是,代码库中的断言占比应该大于0。断言为开发人员提供了一种在代码库中发生缺陷的时刻发现它的好方法。调试是在开发嵌入式系统中最浪费时间并令人沮丧的事情之一。不管开发人员认可的占比是1%、3%还是5%,使用断言肯定对你有利,并会使开发嵌入式软件变得多少有些趣味。
技巧8:将断言用作可执行代码注释
断言可以生成极好的注释!编写出色的表达式可以确切地告诉开发人员在代码的某个给定点应该预料发生什么事情。开发人员应该做好他们断言的架构,帮助人们更清楚地理解系统中发生的事情,进而帮助减少缺陷。
小结
断言是一种出色的工具,但有太多的嵌入式软件开发人员忽视了这一工具。本文讨论的八个技巧只是如何正确使用断言的冰山一角。接下来读者就可以在测试平台中建立和开始使用断言,并研究它们在实际的嵌入式系统中是如何工作的。
‘柒’ c语言 自写字符串函数处理为什么用assert断言,而不是用if来判断。
if是说,这个case和else的case都有可能,而且都我能处理的
assert是说,这是个我不能处理的情况;换句话说,要想用我这个函数,必须的保证assert的东西为真,不然我不能处理
‘捌’ assert的作用是什么
一、assert的基本意思是“坚持”“断言”,即做主观的、自信的、有说服力的阐述。
二、这种“主张”或“断言”尽管有时并无凭据,但是要让别人相信自己的话是有依据的,或要别人对凭据感兴趣。
1、读音:英 [əˈsɜːt] 美 [əˈsɜːrt]
2、释义:明确肯定,断言。
3、语法:assert表示“主张,断言”,指宣称某事如此,并不说它是事实,着重主观自信心。
4、例句:He'. 他明确表态,信心十足地阐述自己的观点。
(8)c语言断言函数扩展阅读
近义词:declare
1、读音:英 [dɪˈkleə(r)] 美 [dɪˈkler]
2、释义:宣告,表明,宣称。
3、语法:declare的基本意思是明确地、清楚地、正式地“宣布,宣告”,多用于官方场合。引申可指“宣称”“断言”“申报”等。
4、例句:必须在这张表格上申报你的收入。