• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 探讨C语言的那些小秘密之断言

探讨C语言的那些小秘密之断言

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c语言断言,c语言中的断言,断言 解 c语言,c断言,安全断言标记语言等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

每次写摘要我都觉得是一件很头疼的事儿,因为我知道摘要真的很重要,它几乎直接就决定了读者的数量。可能花了九六二虎之力写出来的东西,因为摘要的失败而前功尽弃,因为绝大多数的读者看文章之前都会浏览下摘要,如果他们发现摘要“不对口”,没有什么特色和吸引人的地方,那么轻则采用一目十行的方法看完全文,重则对文章判“死刑”,一篇文章的好坏虽然不能用摘要来衡量,但是它却常常被读者用来衡量一篇文章的好坏,从而成为了文章读者数量多少的一个关键因素。下面言归正传来说说断言,如果出于一般性的学习C语言,应付考试的话,我想很少有人会在代码中使用断言,可能有的人在此之前从来没有使用过断言。那么断言的使用到底能给我们的代码带来什么呢?我尽可能的把我所理解的断言的使用讲解清楚,希望我在此所讲的断言能够对你有所帮助,让你以后能够在代码中灵活使用断言。

在讲解之前,我们先来对断言做一个基本的介绍,让大家对断言有一个大致的了解。在使用C语言编写工程代码时,我们总会对某种假设条件进行检查,断言就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式。断言表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真。可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言,而在部署时禁用断言。同样,程序投入运行后,最终用户在遇到问题时可以重新起用断言。它可以快速发现并定位软件问题,同时对系统错误进行自动报警。断言可以对在系统中隐藏很深,用其它手段极难发现的问题可以用断言来进行定位,从而缩短软件问题定位时间,提高系统的可测性。实际应用时,可根据具体情况灵活地设计断言。

通过上面的讲解我们对于断言算是有了一个大概的了解,那么接下来我们就来看看C语言中assert宏在代码中的使用。

原型定义:
void assert( int expression );

assert宏的原型定义在<assert.h>中,其作用是先计算表达式 expression ,如果expression的值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用abort 来终止程序运行。

下面来看看一段代码:

int main( void )
{
      int i;
   i=1;
   assert(i++);


   printf("%d\n",i);

       return 0;
}
</div>
运行结果为:

看看运行结果,因为我们给定的i初始值为1,所以使用assert(i++);语句的时候不会出现错误,进而执行了i++,所以其后的打印语句输出值为2。如果我们把i的初始值改为0,那么就回出现如下错误。
Assertion failed: i++, file E:\fdsa\assert2.cpp, line 8
Press any key to continue

是不是发现根据提示很快就能定位出错点呢?!既然assert这么便于定位出错点,看来的确我们有必要熟练的在代码中使用它,但是什么东西的使用都是有规则的,assert的使用也不例外。

断言语句不是永远会执行,可以屏蔽也可以启用,这就要求assert不管是在屏蔽还是启用的情况下都不能对我们本身代码的功能有所影响,这样的话刚才我们在代码中使用了一句assert(i++);是不妥的,因为我们一旦禁用了assert,i++的语句就得不到执行,对于接下来i值的使用就会出现问题了,所以对于这样的语句我们应该是要分开来实现,写出如下两句来替代, assert(i); i++;,所以这就对于断言的使用有了相应的要求,那么我们一般在什么情况下使用断言呢?主要体现在一下几个方面:

1.可以在预计正常情况下程序不会到达的地方放置断言。(如assert (0);)

2.使用断言测试方法执行的前置条件和后置条件 。

3.使用断言检查类的不变状态,确保任何情况下,某个变量的状态必须满足。(如某个变量的变化范围)

对于上面的前置条件和后置条件可能有的读者还不是很了解,那么看看下面的解释你就明白了。

前置条件断言:代码执行之前必须具备的特性

后置条件断言:代码执行之后必须具备的特性

前后不变断言:代码执行前后不能变化的特性

当然在使用的断言的过程中会有一些我们应该注意的事项和养成一些良好的习惯,如:

1.每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,我们就无法直观的判断是哪个条件失败

2.不能使用改变环境的语句,就像我们上面的代码改变了i变量,在实际编写代码的过程中是不能这样做的

3.assert和后面的语句应空一行,以形成逻辑和视觉上的一致感,也算是一种良好的编程习惯吧,让编写的代码有一种视觉上的美感

4.有的地方,assert不能代替条件过滤

5.放在函数参数的入口处检查传入参数的合法性

6.断言语句不可以有任何边界效应

上面那么多的文字,似乎很枯燥,但是没办法,我们不能急功近利,还是要先坚持看完文字描述部分,这样在下面我们分析代码的过程中就能很快知道为什么会出现那样的问题了,也能在自己编写代码的时候熟练的使用assert,给自己的代码调试带来极大的便利,尤其是你在用C语言做工程项目的时候,如果你能够在你的代码中合理的使用assert,能使你创建更稳定、质量更好且不易于出错的代码。当需要在一个值为FALSE时中断当前操作的话,可以使用断言。单元测试必须使用断言,除了类型检查和单元测试外,断言还提供了一种确定各种特性是否在程序中得到维护的极好的方法。但凡优秀的程序员都能够在自己代码中很好的使用assert,编写出高质量的代码来。

说了assert这么多的有点,当然也要说说它的缺点了。

使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。所以在调试结束后,可以通过在包含#include 的语句之前插入 #define NDEBUG 来禁用assert调用。

接下面分析一下下面的一段代码:

int copy_string(char from[],char to[])
{
 int i=0;
 while(to[i++]=from[i]);

 printf("%s\n",to);

 return 1;
}

int main()
{
 char str[]="this is a string!";
 char dec_str[206];

 printf("%s\n",str);

 assert(copy_string(str,dec_str));

 printf("%s\n",dec_str);

 return 0;
}
</div>
运行结果为:

在以上代码的开头部分我们把#define NDEBUG给注释掉了,所以我们启用了assert,main函数中使用了assert(copy_string(str,dec_str));来实现copy_string函数的调用,在copy_string函数中我们使用了一句return 1,所以最终的函数调用结果就等价于是assert(1),所以接下来继续执行assert下面的打印语句,最终成功的打印了三条输出语句,如果我们把开头的注释部分打开,结果就只能成功的输出起始部分一条打印语句。

以上我们都是在围绕着assert宏在讲解,仅仅是教会大家如何来使用assert宏,那么接下来看看我们如何来实现自己的断言呢?

接下来我们看看另外一段代码:

//#undef  _EXAM_ASSERT_TEST_    //禁用
#define  _EXAM_ASSERT_TEST_   //启用
#ifdef _EXAM_ASSERT_TEST_     //启用断言测试
 void assert_report( const char * file_name, const char * function_name, unsigned int line_no )
{
 printf( "\n[EXAM]Error Report file_name: %s, function_name: %s, line %u\n",
         file_name, function_name, line_no );

}
 #define  ASSERT_REPORT( condition )       \
 do{       \
 if ( condition )       \
  NULL;        \
 else         \
  assert_report( __FILE__, __func__, __LINE__ ); \
 }while(0)
 #else // 禁用断言测试
#define ASSERT_REPORT( condition )  NULL
#endif /* end of ASSERT */
 int main( void )
{
    int i;
    i=0;
   // assert(i++);
   ASSERT_REPORT(i);
     printf("%d\n",i);
        return

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 探讨C语言的那些小秘密之断言

相关文章

  • 2017-05-28详解C++中的增量运算符++和减量运算符--的用法
  • 2017-05-28C语言实现数据结构和双向链表操作
  • 2017-05-28二叉树前序遍历的非递归算法
  • 2017-05-28算法详解之分支限界法的具体实现
  • 2017-05-28深入理解void以及void指针的含义
  • 2017-11-18使用opencv把图片拼接成视频
  • 2017-05-28详解C语言中的getgrgid()函数和getgrnam()函数
  • 2017-05-28C++删除指定文件夹下N天及之前日志文件的方法
  • 2017-05-28详解C++设计模式编程中对访问者模式的运用
  • 2017-05-28C语言小程序 计算第二天日期示例代码

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 哪款C语言编译器(IDE)适合初学者?
    • C语言选择排序算法及实例代码
    • C++基于Directx MMX实现的图像灰度转换代码
    • 使用WindowsAPI实现播放PCM音频的方法
    • 美化你的代码 vb(VBS)代码格式化的实现代码
    • C++ sizeof 实例解析
    • C语言数据结构 链表与归并排序实例详解
    • 数据结构之AVL树详解
    • C语言中结构体(struct)的几种初始化方法
    • 最长公共子序列LCS C++实现

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有