我记得在以前的一篇随笔中,我堆windows下的<assert.h>进行了分析,今天我们来看看gcc中这个文件的定义是怎样的。

【1】assert宏的作用

  assert宏实现断言的作用,一般在源文件中引用格式如下:

#include <assert.h>#undef NDEBUG
assert(expression)

关于assert宏:

  1、当 expression的值为0时进行断言,如果表达式expression的值非零,则不进行断言。

  2、assert宏进行断言的时候,在标准错误输出中输出断言发生的源文件名称:__FILE__ 和断言发生时语句所在的行: __LINE__

  3、可在程序的调试过程中,利用assert宏进行关键点程序进行测试,以输出一些有用的信息,当不需要调试的时候,可以通过定义NDEBUG宏来取消

宏assert的作用。

【2】assert.h

/* Allow this file to be included multiple timeswith different settings of NDEBUG.  *///assert 为C库提供的一种断言机制
//断言用来在标准错误输出流输出信息,并且使程序异常终止
/*断言的机制:*///首先取消 assert 宏的定义,
//这样做的目的是为了防止宏重复被定义
#undef assert
#undef __assert//通过判断是否定义宏 NDEBUG 来判断在源代码中是否需要宏assert
/*如果定义了 NDEBUG 宏,就表示不需要在程序中引用 assert 宏NDEBUG: do not debug否则就在程序中,assert 宏将被执行可以发现assert宏在定义 NDEBUG时,定义很特别,宏参数并没有引用
*/
#ifdef NDEBUG//定义了NDEBUG宏,assert 宏定义为不做任何提示输出#define assert(ignore)  ((void)0)
#elsevoid __eprintf ();        /* Defined in gnulib */#ifdef __STDC__    //定义了__STDC__宏#define assert(expression)  \((void) ((expression) ? 0 : __assert (#expression, __FILE__, __LINE__)))#define __assert(expression, file, lineno)  \(__eprintf ("Failed assertion `%s' at line %d of `%s'.\n",    \expression, lineno, file), 0)#else /* no __STDC__; i.e. -traditional.  */#define assert(expression)  \((void) ((expression) ? 0 : __assert (expression, __FILE__, __LINE__)))#define __assert(expression, file, lineno)  \(__eprintf ("Failed assertion `%s' at line %d of `%s'.\n",    \"expression", lineno, file), 0)#endif /* no __STDC__; i.e. -traditional.  */
#endif

View Code

【3】第一段预处理

//首先取消 assert 宏的定义,
//这样做的目的是为了防止重复定义宏的影响
#undef assert
#undef __assert

  这样做的目的是为了防止 assert 重定义,引起混乱;这样在引用的位置处,就可以取消前面的定义。

【4】标准assert宏定义结构

  通常assert宏定义具有下面的结构

      

  这样结构的目的是为了对用户的 NDEBUG 宏做出正确的响应。

【5】宏代码

//通过判断是否定义宏 NDEBUG 来判断在源代码中是否需要宏assert
/*如果定义了 NDEBUG 宏,就表示不需要在程序中引用 assert 宏NDEBUG: do not debug否则就在程序中,assert 宏将被执行可以发现assert宏在定义 NDEBUG时,定义很特别,宏参数并没有引用
*/
#ifdef NDEBUG//定义了NDEBUG宏,assert 宏定义为不做任何提示输出#define assert(ignore)  ((void)0)
#elsevoid __eprintf ();        /* Defined in gnulib */#ifdef __STDC__    //定义了__STDC__宏#define assert(expression)  \((void) ((expression) ? 0 : __assert (#expression, __FILE__, __LINE__)))#define __assert(expression, file, lineno)  \(__eprintf ("Failed assertion `%s' at line %d of `%s'.\n",    \expression, lineno, file), 0)#else /* no __STDC__; i.e. -traditional.  */#define assert(expression)  \((void) ((expression) ? 0 : __assert (expression, __FILE__, __LINE__)))#define __assert(expression, file, lineno)  \(__eprintf ("Failed assertion `%s' at line %d of `%s'.\n",    \"expression", lineno, file), 0)#endif /* no __STDC__; i.e. -traditional.  */
#endif

  这里我们可以看到,这个宏,其实是定义了两个红: assert 和 __assert

1、assert

  分两种情况:

定义了 __STDC__ 宏时:

#define assert(expression)  \((void) ((expression) ? 0 : __assert (#expression, __FILE__, __LINE__)))

未定义了 __STDC__ 宏时:

#define assert(expression)  \((void) ((expression) ? 0 : __assert (expression, __FILE__, __LINE__)))

  这两者的区别,仅在于 “#” 连接符的作用,如果不用  #expression 这种形式,则宏参数不能使 带引号的字符串, 而用了

#expression 这种形式,assert宏的实际参数既可以是带引号的字符串。

两个预定义宏:

  __FILE__: 返回C成员源文件名

  __LINE__ :返回代码行在C文件中的行数

2、__assert

  这个宏只有一种形式:

#define __assert(expression, file, lineno)  \(__eprintf ("Failed assertion `%s' at line %d of `%s'.\n",    \"expression", lineno, file), 0)

  这个宏,其实是引用了函数 __eprintf() 函数来实现输出,这个函数不是标准的库函数。如果要实现标准assert宏,则不能引用标准库

函数实现,这是因为如果在程序中如果没有包含这些库函数,则会引起异常。

__eprintf() 函数: 

#ifdef L_eprintf
#include <stdio.h>
/* This is used by the `assert' macro.  */
void
__eprintf (string, expression, line, filename)char *string;char *expression;int line;char *filename;
{fprintf (stderr, string, expression, line, filename);fflush (stderr);abort ();
}
#endif

  就是说这个头文件还可以这样:

#ifdef NDEBUG//定义了NDEBUG宏,assert 宏定义为不做任何提示输出#define assert(ignore)  ((void)0)
#elsevoid __eprintf ();  /* Defined in gnulib */#define __assert(expression, file, lineno)  \(__eprintf ("Failed assertion `%s' at line %d of `%s'.\n",    \expression, lineno, file), 0)    #ifdef __STDC__    //定义了__STDC__宏#define assert(expression)  \((void) ((expression) ? 0 : __assert (#expression, __FILE__, __LINE__)))    #else /* no __STDC__; i.e. -traditional.  */#define assert(expression)  \((void) ((expression) ? 0 : __assert (expression, __FILE__, __LINE__)))#endif /* no __STDC__; i.e. -traditional.  */
#endif

【6】微软VS 2008 代码比较

/***
*assert.h - define the assert macro
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       Defines the assert(exp) macro.
*       [ANSI/System V]
*
*       [Public]
*
****/#include <crtdefs.h>#undef  assert#ifdef  NDEBUG#define assert(_Expression)     ((void)0)#else#ifdef  __cplusplus
extern "C" {
#endif_CRTIMP void __cdecl _wassert(_In_z_ const wchar_t * _Message, _In_z_ const wchar_t *_File, _In_ unsigned _Line);#ifdef  __cplusplus
}
#endif#define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )#endif  /* NDEBUG */

  不知道,有没有专门介绍gcc编译器源代码的书籍,我知道有一本书gcc internal, 是英语版的,看起来很废力,有没有人知道中文的这样的书籍;

那位大侠不吝赐教,告诉我一本这样的书,或者这样的论坛,我找了好久也没有发现一个合意的。

转载于:https://www.cnblogs.com/volcanol/archive/2013/05/25/3099268.html

【C语言学习趣事】_GCC源代码分析_2_assert.h相关推荐

  1. C语言学习趣事_之_大数运算_加法

    C语言学习趣事_大数运算_之加法 1.引子    在C语言中,因为预定义的自然数类型的大小是有上下限度的,这就决定了在进行数的运算的时候,必然受到限制,同时因为C语言是最接近汇编的一种程序设计语言,并 ...

  2. 数据结构背包问题c语言思路,C语言学习趣事_数据结构_经典命题_1_背包问题_分析_1...

    /*1.问题描述 假设有一个能装入总体积为T的背包和n件体积分别为w1,w2,-wn的物品, 能否从n件物品中挑选若干件恰好装满背包,即使w1+w2+-+wm=T, 要求找出所有满足上述条件的解. 例 ...

  3. Volley简单学习使用五—— 源代码分析三

    一.Volley工作流程图: 二.Network     在NetworkDispatcher中须要处理的网络请求.由以下进行处理: NetworkResponse networkResponse = ...

  4. C语言学习趣事_你不知道的C语言应用

    一.引 我一直不明白"文人相轻"是什么意思,也许就是说:文人清客之间互相瞧不起的事情吧.但对于我来说,文人相轻就是表示:无知者无畏. 无论你的某一方面的语言学的怎么样,怎么样的牛逼 ...

  5. 语言学习游戏的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告

    报告页数: 150 图表数: 100 报告价格:¥16800 本文研究全球与中国市场语言学习游戏的发展现状及未来发展趋势,分别从生产和消费的角度分析语言学习游戏的主要生产地区.主要消费地区以及主要的生 ...

  6. 易语言.尘土界面库2.0版源代码分析(1):缘起

    作者:liigo 原文链接:http://blog.csdn.net/liigo/archive/2009/06/23/4292691.aspx 转载请注明出处:http://blog.csdn.ne ...

  7. 利用计算机语言实现ID3算法,机器学习之决策树学习-id3算法-原理分析及c语言代码实现.pdf...

    机器学习之决策树学习-id3算法-原理分析及c语言代码实现.pdf 还剩 23页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保 ...

  8. BT源代码学习心得(十):客户端源代码分析(相关对象一览) -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(十):客户端源代码分析(相关对象一览) Author:wolfenstein(NeverSayNever), BitTorrent/download.py中的Multitorren ...

  9. BT源代码学习心得(九):客户端源代码分析(图形界面浅析) -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(九):客户端源代码分析(图形界面浅析)  author:wolfenstein 客户端将从btdownloadgui.py开始进行分析,这样可以顺便把Python中的GUI编程也看 ...

最新文章

  1. 真正能解决 Windows 7下安装Office 2007—2010出现1402和1406类错误的方法
  2. python mulit函数_python – 将函数应用于MultiIndex pandas.DataFrame列
  3. linux tomcat php配置文件在哪个文件夹下,tomcat下,怎么安配备置php ?(linux系统)
  4. [HNOI2003]多边形
  5. 485通讯线是几芯的_RS485通讯线是几芯电缆
  6. SKU与SPU的区别与联系
  7. 自动化c语言课程设计,自动化与电气工程学院C语言课程设计报告.doc
  8. mysql表空间加密
  9. 任务栏优化工具TrueLaunchBar
  10. 使用spark-submit工具提交Spark作业
  11. win10 SystemParametersInfo 设置屏保 不好使_[教程]win10 ,ubuntu双系统安装避坑指南
  12. java遍历变量_java – 循环遍历众多变量
  13. 今日分享非技术之图片大小不得超过80kb
  14. 物联网教育现状和前景
  15. 利用pandas进行exceld 的列相加求和
  16. 小学计算机集体备课活动记录,小学科学集体备课活动记录
  17. 多线程MT和多线程MD的区别
  18. 新闻订阅及新闻内容展示系统(Python+Django+scrapy)
  19. ps 蒙板的使用和理解。
  20. 【ML】随机森林(Random Forest,RF)

热门文章

  1. 设计模式快速学习(六)模板模式
  2. BZOJ4890 洛谷3761:[TJOI2017]城市——题解
  3. 台积电将开始量产 iPhone 8 A11 芯片 10纳米工艺
  4. NUC1003 Hangover
  5. java多线程——饥饿和公平
  6. 前端移动开发之安卓下存在的问题
  7. Linux新内核修复14年古老bug
  8. HP-UX Root密码被锁定的非关机情况下解决方案
  9. 从0到1,一步步开发React的loading组件,并发布到npm上
  10. dotnet core高吞吐Http api服务组件FastHttpApi