第六篇:使用预处理器帮助调试

穆晨 穆晨     2022-08-21     127

关键词:

前言

       你是否遇到过以下情况?

       情况一:为了调试方便,代码中夹杂各种cout语句。当调试好了,把这些语句删了,运行“正式版”后,又发现新问题,只得把这些cout语句一个个添加回去再进行调试。如此不断循环。

       情况二:希望在代码中获取到源文件的文件名,当前代码行号,编译时间等信息。

       情况三:纠结于是否实现某些概率极低(几乎不存在)的错误检测

       如果有,那么这篇随笔适合你,或者说,预处理器带来的调试技术适合你。

技巧一:设置调试区代码开关

       请看下面的源代码:

 1 #include <iostream>
 2  
 3 using namespace std;
 4  
 5 int main()
 6 {
 7     /*
 8     * 源代码区一
 9     */
10 
11     #ifdef DEBUG1
12     cout << "DEBUG1" << endl;
13     #endif
14  
15     /*
16      * 源代码区二
17     */
18 
19     #ifdef DEBUG2
20     cout << "DEBUG2" << endl;
21     #endif
22 
23     /*
24      * 源代码区三
25     */
26 
27     return 0;
28  }

       两段包含cout语句的代码段都是调试语句,而两个宏DEBUG1和DEBUG2就是所谓的开关。现在假设我想执行上面的那段调试代码,则可以输入以下指令打开DEBUG1开关并完成编译(这条命令等效于在源文件开头加上#define DEBUG1再编译):

1 g++ -DDEBUG1 1.cpp -o run

       运行结果如下:

  

  结果显示DEBUG1开关对应的调试语句得到执行。可以用同样的方法操纵开关DEBUG2及其对应调试代码。明白了吧,你可以通过打开开关自由地选择需要编译并运行的调试区代码

技巧二:使用预定义宏获取相关信息

       预处理器提供了一些预定义的宏可获取编译,文件的相关信息,参见下面代码:

 1 #include <iostream>
 2 
 3 using namespace std; 
 4 
 5 int main()
 6 {
 7     cout << "文件名: " << __FILE__ << endl;
 8     cout << "当前行号: " << __LINE__ << endl;
 9     cout << "编译日期: " << __DATE__ << endl;
10     cout << "编译时间: " << __TIME__ << endl;
11 
12     return 0;
13 }

       运行结果:

       

技巧三:使用assert断言宏确保某个条件不发生

  基本格式为 assert(表达式)。当表达式为真,语句不做任何事情,否则语句输出错误并终止程序执行,请看下面代码:

 1 #include <iostream>
 2 #include <cassert>    // 要使用assert断言宏必须包含这个头文件
 3  
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     int t=0;
 9     cin >> t;
10 
11     assert (t !=0);
12     cout << "t: " << t << endl;
13  
14     return 0;
15 }

       assert在这里的作用是确保t不等于0。如果t=0,程序会弹出错误并停止运行。编译代码并运行,

       当输入为0时运行结果:

       

       当输入其他数字时运行结果:

       

       最后要强调的是,assert只是调试工具,它绝对不能代替逻辑检查参与到异常处理中

重构之路第六篇——处理概括关系

1PullupField(字段上移)2PullupMethod(函数上移)3PullupConstructorBody(构造函数本体上移)4PushDownMethod(函数下移)5PushDownField(字段下移)6ExtractSubclass(提炼子类)7ExtractSuperclass(提炼超类)8ExtractInterface(提炼接口)9CollapseHierarchy(折叠 查看详情

第六篇:数据预处理-数据标准化

 前言    在进行缺失,异常处理之后,往往要对数据进行变换。    变换有多种情况,主要是以下两种:    -规范化:对数据进行一定比例的缩放,让它实质落入某个具体区间。 ... 查看详情

jsp第六篇自定义标签之传统标签

为什么要使用自定义标签?JSTL标签库只提供了简单的输出等功能,没有实现任何的HTML代码封装,并且某些复杂类型转换,或者逻辑处理的时候,JSTL标签库完成不了,需要自定义标签!编写自定义标签的步骤:编写一个实现Tag接... 查看详情

深入学习jquery选择器系列第六篇——过滤选择器之状态选择器

×目录[1]焦点状态[2]哈希状态[3]动画状态[4]显隐状态前面的话  过滤选择器的内容非常多,本文介绍过滤选择器的最后一部分——状态选择器 焦点状态:focus  :focus选择器选择当前获得焦点的元素<div><button... 查看详情

第六篇函数对象函数嵌套名称空间与作用域装饰器(代码片段)

一、函数对象函数是第一类对象,即函数可以当作数据传递#1可以被引用#2可以当作参数传递#3返回值可以是函数#4可以当作容器类型的元素利用该特性,优雅的取代多分支的ifdeffoo():print(‘foo‘)defbar():print(‘bar‘)dic=‘foo‘:foo,‘... 查看详情

第六篇:元数据管理之“灵魂”三问

元数据管理作为企业数据治理的基础工作,贯穿数据产生、加工和使用的全生命周期,是有效管理和使用数据的基础和前提,通过元数据管理可以实现数据的可见、可懂、可用,帮助业务快速获取所需数据。本文... 查看详情

第六篇:元数据管理之“灵魂”三问

元数据管理作为企业数据治理的基础工作,贯穿数据产生、加工和使用的全生命周期,是有效管理和使用数据的基础和前提,通过元数据管理可以实现数据的可见、可懂、可用,帮助业务快速获取所需数据。本文... 查看详情

flask第六篇flask中路由系统(代码片段)

Flask中的路由系统其实我们并不陌生了,从一开始到现在都一直在应用@app.route("/",methods=["GET","POST"])为什么要这么用?其中的工作原理我们知道多少?请关注跟DragonFire学Flask之路由系统,这里有你想要的答案 1.@app.route()装饰器中的... 查看详情

第六篇scrum冲刺博客

一、DailyScrumMeeting照片二、每个人的工作成员ItemID已完成工作明天计划完成的工作遇到的困难张鸿o1已完成工作,实现积分变换,碰撞检测将其他剩余功能进行整合结束场景的生成夏浚杰o2将昨天写的代码出现的漏洞补上将整体代... 查看详情

第六篇数据类型

整数(int)Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样,例如:1,100,-8080,0,等等。浮点数(float)浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个... 查看详情

关于ajax第六篇

使用回调函数回调函数是一种以参数形式传递给另一个函数的函数。如果您的网站上存在多个AJAX任务,那么您应该为创建XMLHttpRequest对象编写一个标准的函数,并为每个AJAX任务调用该函数。该函数调用应该包含URL以及发生onreadys... 查看详情

第六篇:面向对象

第六篇:面向对象  PYTHON-面向对象类绑定方法PYTHON-面向对象继承派生PYTHON-面向对象-练习-王者荣耀对砍游戏  查看详情

springcloud-第六篇hystrix参数配置

1:概述Hystrix使用Archaius作为配置属性的默认实现。官方配置文档:https://github.com/Netflix/Hystrix/wiki/Configuration每个属性有四个优先级,依次增大:1:代码的全局默认值2:动态全局默认属性可以使用全局属性文件来更改全局默认值... 查看详情

第六篇商城系统-实现规格参数和销售属性(代码片段)

规格参数1.基础页面  基础页面和属性组的页面非常类似,所以我们先创建了该页面,直接使用2.添加规格参数  规格数据需要绑定对应的属性组,所以我们在后台通过VO对象来接收信息在后端处理添加的逻辑就需... 查看详情

第六篇vggnet——模型精讲

文章目录 查看详情

扫盲记-第六篇--normalization

...乘除)。它通过将数据进行偏移和尺度缩放调整,在数据预处理时是非常常见的操作,在网络的中间层也很频繁的被使用。1.线性归一化最简单来说,归一化是指将数据约束到固定的分布范围,比如8位图像的0~255像素值,比如0~... 查看详情

构建之法—第六篇

这周的学习关于典型用户和场景。VisualStudio是一个非常成功的软件开发集成环境,支持项目管理,测试工具,以及第三方的插件。对于定义典型用户,我们有不同的需求:受欢迎的典型用户和不受欢迎的典型用户,其中,受欢迎... 查看详情

第六篇:组件数据局部化处理(代码片段)

组件数据局部化处理同一个页面可能同时复用一个组件两次,但每个组件的数据不相同,需要区分开,因此我们需要对组件的数据局部化处理不管页面组件还是小组件,否可能被多次复用复用组件的原因,其实就是复用组件的页... 查看详情