【C语言学习趣事】_GCC源代码分析_2_assert.h
我记得在以前的一篇随笔中,我堆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相关推荐
- C语言学习趣事_之_大数运算_加法
C语言学习趣事_大数运算_之加法 1.引子 在C语言中,因为预定义的自然数类型的大小是有上下限度的,这就决定了在进行数的运算的时候,必然受到限制,同时因为C语言是最接近汇编的一种程序设计语言,并 ...
- 数据结构背包问题c语言思路,C语言学习趣事_数据结构_经典命题_1_背包问题_分析_1...
/*1.问题描述 假设有一个能装入总体积为T的背包和n件体积分别为w1,w2,-wn的物品, 能否从n件物品中挑选若干件恰好装满背包,即使w1+w2+-+wm=T, 要求找出所有满足上述条件的解. 例 ...
- Volley简单学习使用五—— 源代码分析三
一.Volley工作流程图: 二.Network 在NetworkDispatcher中须要处理的网络请求.由以下进行处理: NetworkResponse networkResponse = ...
- C语言学习趣事_你不知道的C语言应用
一.引 我一直不明白"文人相轻"是什么意思,也许就是说:文人清客之间互相瞧不起的事情吧.但对于我来说,文人相轻就是表示:无知者无畏. 无论你的某一方面的语言学的怎么样,怎么样的牛逼 ...
- 语言学习游戏的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
报告页数: 150 图表数: 100 报告价格:¥16800 本文研究全球与中国市场语言学习游戏的发展现状及未来发展趋势,分别从生产和消费的角度分析语言学习游戏的主要生产地区.主要消费地区以及主要的生 ...
- 易语言.尘土界面库2.0版源代码分析(1):缘起
作者:liigo 原文链接:http://blog.csdn.net/liigo/archive/2009/06/23/4292691.aspx 转载请注明出处:http://blog.csdn.ne ...
- 利用计算机语言实现ID3算法,机器学习之决策树学习-id3算法-原理分析及c语言代码实现.pdf...
机器学习之决策树学习-id3算法-原理分析及c语言代码实现.pdf 还剩 23页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保 ...
- BT源代码学习心得(十):客户端源代码分析(相关对象一览) -- 转贴自 wolfenstein (NeverSayNever)
BT源代码学习心得(十):客户端源代码分析(相关对象一览) Author:wolfenstein(NeverSayNever), BitTorrent/download.py中的Multitorren ...
- BT源代码学习心得(九):客户端源代码分析(图形界面浅析) -- 转贴自 wolfenstein (NeverSayNever)
BT源代码学习心得(九):客户端源代码分析(图形界面浅析) author:wolfenstein 客户端将从btdownloadgui.py开始进行分析,这样可以顺便把Python中的GUI编程也看 ...
最新文章
- 真正能解决 Windows 7下安装Office 2007—2010出现1402和1406类错误的方法
- python mulit函数_python – 将函数应用于MultiIndex pandas.DataFrame列
- linux tomcat php配置文件在哪个文件夹下,tomcat下,怎么安配备置php ?(linux系统)
- [HNOI2003]多边形
- 485通讯线是几芯的_RS485通讯线是几芯电缆
- SKU与SPU的区别与联系
- 自动化c语言课程设计,自动化与电气工程学院C语言课程设计报告.doc
- mysql表空间加密
- 任务栏优化工具TrueLaunchBar
- 使用spark-submit工具提交Spark作业
- win10 SystemParametersInfo 设置屏保 不好使_[教程]win10 ,ubuntu双系统安装避坑指南
- java遍历变量_java – 循环遍历众多变量
- 今日分享非技术之图片大小不得超过80kb
- 物联网教育现状和前景
- 利用pandas进行exceld 的列相加求和
- 小学计算机集体备课活动记录,小学科学集体备课活动记录
- 多线程MT和多线程MD的区别
- 新闻订阅及新闻内容展示系统(Python+Django+scrapy)
- ps 蒙板的使用和理解。
- 【ML】随机森林(Random Forest,RF)