C 标准库系列之assert.h

  先简单介绍一下<assert.h>头文件,该头文件的目的便是提供一个宏assert的定义,即可以在程序必要的地方使用其进行断言处理;断言在程序中的作用是当在调试模式下时,
若程序给出的前提条件没有满足或是没有达到预期预定的条件便会出现断言为假,此时程序会异常终止,调试时会挂在该断言失败处(即结果为false的断言位置)并打印或者显示断言
失败的消息。

  assert函数实际上是一个宏,glibc和微软的c标准库实现均是如此;如glibc的:
    # define assert(expr) \
    ((expr) \
    ? __ASSERT_VOID_CAST (0) \
    : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION))

  可以看到该宏实际上是通过三目运算符,判断表达式expr的真假,执行相应的处理,当为真是执行__ASSERT_VOID_CAST(0),该函数实际上也是一个宏;
即# define __ASSERT_VOID_CAST static_cast<void>,其实际上什么也没有做,此外__assert_fail函数便是用以打印断言失败的消息并终止的函数;该函数参数分别为断言表达式,
当前的文件路径名,当前行号,以及断言函数名;而这些参数通过相应的宏提供。
__assert_fail函数内部调用__assert_fail_base,其提供格式化打印输出,__assert_fail_base内部分配堆空间存储格式化后的信息,并调用__fxprintf以及fflush向stderr
标准输出刷字符串;此后便释放该分配的堆空间,并调用abort终止程序;微软的提供了类似的实现,不过其针对Unicode和多字节提供不同的实现方式,当为Unicode时,其assert宏
失败时调用_assert函数,同样的_assert函数内部调用_set_error_mode来控制设置输出,sprintf格式化错误信息,此后通过GetStdHandle(STD_ERROR_HANDLE)获取到错误输出设备
并调用WriteConsole向该错误输出设备输出字符串信息,此后同样调用abort来终止程序;而当为多字节模式时,便调用_ftprintf以及fflush向stderr标准输出刷字符串;

  assert函数,其参数为int类型,故只要表达式可计算结果可以转化为int类型的均可。

  assert断言仅在Debug模式下有效,对于发行Release或者NDEBUG模式下其宏声明类似于# define assert(expr) (__ASSERT_VOID_CAST (0))或者#define assert(ignore) ((void)0);
即什么也不做,也包括表达式的值也不会计算,这个一定要切记!此处若使用不当可能引入BUG,导致调式和开发模式下程序有不同的表现行为。

  顺便提一下,abort函数也是C语言标准库stdlib.h中的一员。

  此外C11中提供了static_assert宏,若编译器支持C11,则建议使用该宏来进行断言处理,此外此后的C语言标准库分析均暂时不针对C11的标准库。

时间: 2024-10-07 22:55:40

C 标准库系列之assert.h的相关文章

C 标准库系列之locale.h

locale.h 区域设置相关,主要针对时间日期.货币格式.字符控制.数字格式等以满足某区域的设置需要. locale设置类别主要包括以下几个宏定义的类别: LC_ALL:设置所有的类别: LC_COLLATE:设置控制整理顺序: LC_CTYPE:设置字符分类: LC_MONETARY:设置货币的格式: LC_NUMERIC:设置数字格式,如小数点后位数: LC_TIME:设置时间日期格式: 某些C标准库实现还提供了其他类型的设置类别扩展,如glibc实现约有12种类型:不过除以上类别外的其他

C 标准库系列之errno.h

errno.h 提供了一个整数全局变量errno,当系统调用或者库函数的错误事件发生时可能会修改该值,指明错误的原因,该值可在任何需要的地方被修改:一般情况不为0的值表示出现了异常或者错误. errno.h中定义了一系列的错误代码,以E开头的宏. glibc中extern int errno来声明定义该错误值:此外其他的E开头的宏EDOM.EILSEQ.ERANGE.EOWNERDEAD等. 微软提供的为一个函数,errno被宏定义#define errno (*_errno()):_errno

C 标准库系列之limits.h

limits.h 类似于float.h,其定义了一些列类型的值的范围.限制值,也就是说该类型的值不可以大于该上界或者小于该类型值的下界: glibc中宏定义了一下的值: # define MB_LEN_MAX 16 // 多字节字符的最大字节(byte)数为16位 # define CHAR_BIT 8 // 1个字符所占的字节位数8位 # define SCHAR_MIN (-128) // 一个有符号字符的最小值 # define SCHAR_MAX 127 // 一个有符号字符的最大值 #

22Python标准库系列之Redis模块

Python标准库系列之Redis模块 What is redis? Redis is an open source (BSD licensed), in-memory data structure store, used as database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, b

9Python标准库系列之time模块

Python标准库系列之time模块 This module provides various functions to manipulate time values. 方法名 说明 time.sleep(int) 等待时间 time.time() 输出时间戳,从1970年1月1号到现在用了多少秒 time.ctime() 返回当前的系统时间 time.gmtime() 将时间戳转换成struct_time格式 time.localtime() 以struct_time格式返回本地时间 time

10Python全栈之路系列之深浅拷贝标准库系列之datetime模块

Python标准库系列之datetime模块 Fast implementation of the datetime type. 功能 说明 datetime.date.today() 打印输出当前的系统日期 datetime.date.fromtimestamp(time.time()) 将时间戳转成日期格式 datetime.datetime.now() 打印当前的系统时间 current_time.replace(2016,5,12) 返回当前时间,但指定的值将被替换 datetime.d

1Python标准库系列之模块介绍

Python标准库系列之模块介绍 Python的模块其实就是封装了一个或者多个功能的代码集合,以便于重用,模块可以是一个文件也可以是一个目录,目录的形式称作包. 模块分类 内置模块 内置模块可以理解成当你安装好python环境之后,直接可以使用import导入的就是内置模块,默认模块路径为:C:\Python35\lib,你也可以通过以下方式获取内置模块的路径:  # 导入sys模块  >>> import sys  # 最后一个目录就是内置模块的路径  >>> for

11Python标准库系列之configparser模块

Python标准库系列之configparser模块 This module provides the ConfigParser class which implements a basic configuration language which provides a structure similar to what's found in Microsoft Windows INI files. You can use this to write Python programs which

4Python标准库系列之sys模块

Python标准库系列之sys模块 This module provides access to some variables used or maintained by the interpreter and to functions that interact strongly with the interpreter. It is always available. sys模块用于提供对解释器相关的操作 模块方法 解释说明 sys.argv 传递到Python脚本的命令行参数列表,第一个元