IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C++】assert -> 正文阅读

[C++知识库]【C++】assert

clpusplus /assert
cppreference /assert

Part1 Assert

assert旨在捕获程序员的编程错误(例如传入非法参数),而不是用户错误或运行时错误(如返回错误值或在 C++ 中抛出异常),因为它通常在程序退出调试阶段后被禁用。在程序运行时,一旦遇到断言不成立,程序即会报错终止,以方便程序调试。

assert是一个function-like marco,那么我们在程序中中调用assert(condition),编译器就会去看assert的宏定义,这个宏定义是在编译时处理好的。即:

  • 如果当前没有定义NDEBUG,则执行# define assert(condition) /*implementation defined*/
  • if condition 计算结果为 0,说明断言失败,程序崩溃:assert在standard error output中写入一条诊断信息,并调用std::abort终止程序执行。
  • else,继续执行
  • 如果定义了NDEBUG,则执行# define assert(condition) ((void)0),即assert不做任何事情
#ifdef NDEBUG											//如果定义了NDEBUG
#  define assert(condition) ((void)0)					//assert被定义成0
#else													//否则
#  define assert(condition) \							//宏定义常用技巧:使用‘\’表示分行
	/*implementation defined*/							
#endif													//条件预编译结束

以下是三点解释:

  1. 宏assert的定义依赖于另一个宏NDEBUG。assert使用太多会影响系统性能,因此需要通过宏,把assert编译成debug版本release版本。尽管NDEBUG不是标准库中的宏,但是基本上编译器都在实现<cassert>的时候对其做了定义,因此编程的时候也要先#include<cassert>再使用。如果定义了NDEBUG,说明当前是release版本,不执行assert。

  2. 诊断信息的细节取决于特定的库实现,但至少应包括:断言失败的表达式源文件的名称__FILE__(预定义宏,输出的是整个路径,路径中包含了文件名)和抛出异常的表达式在源文件中的行号__LINE__(预定义宏),在C++11后,一般还包括表达式所属函数的名称__func__((预定义变量,返回以 null 结尾的 const char 字符数组,该数组包含函数名称)。这些宏被预定义在<cstdio>中。
    错误信息格式举例:

    a.out: main.cpp:13: int main(): \
    Assertion `((void)"There are five lights", 2+2==5)' failed.
    //编译生成的文件名:源文件名:行数:函数名:断言失败表达式(只有condition)
    //assert可以指定第二个参数,断言失败所返回的字符串,这里是"There are five lights"
    
  3. assert(condition)说到底还是一个function-like marco,只是在编译时进行简单的替换, 因此condition中任何不受括号保护的逗号都被解释为宏参数分隔符,常见于模板参数列表和列表初始化中:

    assert(std::is_same_v<int, int>); // error: assert does not take two arguments
    assert((std::is_same_v<int, int>)); // OK: one argument
    static_assert(std::is_same_v<int, int>); // OK: not a macro
    

Part2 宏的编写技巧

——do-while合并多条语句
【错误示例1】

#define M() a(); b()
if (cond)
    M();
else
    c();

/* 预处理后 */
if (cond)
    a(); b(); 				//a()的; 说明if已经结束,后面的逻辑全部不对
else          
    c();

【错误示例2】

#define M() { a(); b(); }

/* 预处理后 */
if (cond)
    { a(); b(); }; 			//最后的分号代表 if 语句结束
else               
    c();

【正确写法】

#define M() do { a(); b(); } while(0)

/* 预处理后 */
if (cond)
    do { a(); b(); } while(0);
else
    c();

Part3 Static Assert(Since C++ 11)

cppreference /Declarations
cppreference /static_assert declaration

关键字static往往代表将运行时处理的内容提前至编译时处理,对于assert来说同样如此

语法格式:

static_assert ( bool-constexpr , message )					//since C++11
static_assert ( bool-constexpr )							//since C++17

第一个参数是布尔类型的常量表达式,即可以在编译时计算的表达式。事实上assert的condition并未明确规定布尔类型,但是C++17明确指出如果condition是布尔类型表达式,则必须为常量表达式。这是一件很好理解的事情,因为static_assert发生在编译期,如果其condition无法在编译期计算就相当麻烦。而C++17后,把这种bool-constexpr放在编译期去做,本质和constexpr关键字所做的没什么区别,都是缓解了运行期的压力。
第二个参数在C++ 17后变为可选参数。

  • static_assert的断言表达式的结果必须是在编译时期可以计算的表达式,即必须是常量表达式,一旦表达式里出现变量,报错。

    static_assert(sizeof(int) == 4, "64-bit code generation is not supported.");		//OK
    static_assert(n > 0, "value must > 0");										//ill-formed
    
  • 如果常量表达式依赖于某些模板参数,则延迟到模板实例化时再进行演算,这就让检查模板参数也成为了可能。

    template <typename T, typename U> int bit_copy(T& a, U& b)
    {
    	static_assert(sizeof(b) == sizeof(a), "template parameter size no equal!");
    };
    
  • 由于static_assert是编译期断言,不生成目标代码,因此static_assert不会造成任何运行期性能损失。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-04 12:40:48  更:2021-10-04 12:43:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 3:36:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计