第63课 C语言异常处理
1. 异常的概念
(1)程序在运行过程中可能产生异常
(2)异常(Exception)与Bug的区别
①异常是程序运行时可预料的执行分支
②Bug是程序是的错误,是不被预期的运行方式
2. 异常和Bug的对比
(1)异常:如运行时产生除0的情况、需要打开的外部文件不存在、数组访问时越界
(2)Bug:如使用野指针、堆数组使用结束后未释放、选择排序无法处理长度为0的数组
3. C语言经典处理方式:if-else
(1)示例程序
void func(…)
{
if(判断是否产生异常)
{
正常情况代码逻辑
}
else
{
异常情况代码逻辑
}
}
【编程实验】除法操作异常处理
#include <iostream>
using namespace std;
double divide(double a, double b, int* valid)
{
const double delta = 0.000000000000001;
;
if(!((-delta < b) && (b < delta)))
{
ret = a / b;
*valid = ; //正常
}
else
{
*valid = ; //除0错误
}
return ret;
}
int main()
{
;
, , &valid); //当第3个参数为NULL时,还是会出问题
if(valid)
{
cout << "r = " << r << endl;
}
else
{
cout << "Divide by zero..." << endl;
}
;
}
(2)缺陷
①divide函数有3个参数,难以理解其用途
②divide函数调用后必须判断valid代表的结果:true表示结果正常,false表示出现异常
4. C语言异常处理的优化方式
(1)通过setjmp()和longjmp()进行优化
①包含头文件#include <setjmp.h>或<csetjmp>
②int setjmp(jmp_buf env):将当前上下文保存在jum_buf结构体中,以供以后longjmp()恢复状态信息时使用。如果是直接调用setjmp(),那么返回值为0;如果是由于调用longjmp()而调用setjmp(),那么返回值非0。setjmp()只能在某些特定情况下调用,如在if语句、 switch语句及循环语句的条件测试部分以及一些简单的关系表达式中。
③void longjmp(jmp_buf env, int val):用于恢复由最近一次调用setjmp()时保存到env的状态信息。当它执行完时,程序执行流会跳转到setjmp()那行,并根据重新执行setjmp(),但此时的setjmp()得到的返回值是val。
【编程实验】除法操作异常处理优化
#include <iostream>
#include <csetjmp> //for setjmp、longjmp();
using namespace std;
static jmp_buf env; //须定义全局的上下文环境
double divide(double a, double b)
{
const double delta = 0.000000000000001;
;
if(!((-delta < b) && (b < delta)))
{
ret = a / b;
}
else
{
longjmp(env, ); //当错误发生时会跳转到setjmp那么的代码
//处,重新执行setjmp并把其的返回值设为1
}
return ret;
}
int main()
{
) //先保存上下文环境,刚调用时返回值为0
{
, );
cout << "r = " << r << endl;
}
else
{
cout << "Divide by zero..." << endl;
}
;
}
(2)缺陷
①引入setjmp()和longjmp()必然涉及到使用全局变量
②暴力跳转导致代码可读性降低
③本质还是if-else异常处理方式
5. C语言异常处理存在的通病
(1)会使程序逻辑中混入大量的处理异常的代码
(2)正常逻辑和异常处理代码混合在一起,导致代码迅速膨胀,难以维护。
【实例分析】异常处理代码分析
#include <iostream>
using namespace std;
#define SUCCESS 0
#define INVALID_POINTER -1
#define INVALID_LENGTH -2
#define INVALID_PARAMETER -3
int MemSet(void* dest, unsigned int length, unsigned char v)
{
if(dest == NULL)
{
return INVALID_POINTER;
}
)
{
return INVALID_LENGTH;
}
) || (v > ) )
{
return INVALID_PARAMETER;
}
unsigned char* p = (unsigned char*)dest;
; i< length; i++)
{
//将char赋值给int。
//1.如果是char,则最高位为符号位,char赋值给int时会扩展最高位
//2.如果是unsigned,则不会扩展,即低8位为char的值,其余24位为0
p[i] = v;
}
return SUCCESS;
}
int main()
{
];
);
//正常处理与异常处理的代码混杂,不容易看出哪些是正常处理时的代码
//哪些是异常发生时应处理的代码(特别是当返回值用数字表示,而不是这里有意义的常量名时)
if(ret == SUCCESS)
{
}
else if(ret == INVALID_POINTER)
{
}
else if(ret == INVALID_LENGTH)
{
}
else if(ret == INVALID_PARAMETER)
{
}
;
}
6. 小结
(1)程序中不可避免的会发生异常
(2)异常是在开发阶段就可以预见的运行时问题
(3)C语言中通过经典的if-else
(4)C++中存在更好的异常处理方式
第63课 C语言异常处理的更多相关文章
- go语言异常处理
go语言异常处理 error接口 go语言引入了一个关于错误错里的标准模式,即error接口,该接口的定义如下: type error interface{ Error() string } 对于要返 ...
- Go语言异常处理defer\panic\recover
Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱.因为开发者很容易滥用异常, ...
- [原创]零基础R语言教程---第二课---R语言入门
这节教程简单描述了R语言中常用的数据类型, 向量,字符串,矩阵,列表,数据框,以及附带了一个小例子 对于这节课所附带的例子需要做下列补充: 1.这个例子面向于对整列的数据进行预测 2.如果你需要求单行 ...
- c语言异常处理机制
异常处理机制:setjmp()函数与longjmp()函数 C标准库提供两个特殊的函数:setjmp() 及 longjmp(),这两个函数是结构化异常的基础,正是利用这两个函数的特性来实现异常. 所 ...
- 第一课 C语言简明教程
1序言: 1与Java.C#等高级语言相比,C语言使用简单但是也非常重要更容易出错,到目前为止基本上操作系统的内核代码超过百分之九十使用C语言完成,因此学好C语言是学好计算机这门课程的基础,特别是进入 ...
- 3.06课·········C#语言基础
Main函数: static void Main(string [] args){ }程序代码需要写在Main函数的花括号内. 一.输出:Console.WriteLine("这是我的第一个 ...
- C++_系列自学课程_第_9_课_C语言风格字符串_《C++ Primer 第四版》
前面说了写关于数组和指针的内容,这次在这里讨论一下字符串,讨论一下C语言风格的字符串. 在C语言里面我们利用字符数组来对字符串进行处理, 在C++里面我们前面说过一种类类型string可以对字符串进行 ...
- Asp.Net Web API 2第七课——Web API异常处理
前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文主要来讲解Asp.Ne ...
- C语言异常处理和连接数据库
#include <stdio.h> #include <setjmp.h> jmp_buf j; void Exception(void); double diva(doub ...
随机推荐
- [deviceone开发]-拼图小游戏
一.简介 九宫格小游戏,可从本地图库载入一张图片,填充到9个ImageView,另涉及Timer计时.图库控件. 每个格子都是相同的控件,动态添加到首页中的,在初始化后,响应touch事件,之后通过多 ...
- 记STM32F030多通道ADC DMA读取乱序问题
问题描述通过 uint16_t ConvData[8]保存DMA搬运的ADC转换数值,但是这个数组数值的顺序总是和ADC不是顺序对应的.比如用7个通道的ADC,当设置ADC_InitStructure ...
- 微信小程序管理后台介绍
微信小程序的管理后台,每次进入都需要扫码,还是特别不爽,现在微信小程序还没正式发布,很多人都还没看到管理后台,这里抢先发布出来 ------------------------------------ ...
- Android - ADB 的使用
一.什么是ADB? 1.ADB全称Android Debug Bridge, 是android sdk里的一个工具,用这个工具可以直接操作管理android模拟器或者真实的andriod设备 2.AD ...
- Android项目开发实战-2048游戏
<2048>是一款比较流行的数字游戏,最早于2014年3月20日发行.原版2048首先在GitHub上发布,原作者是Gabriele Cirulli,后被移植到各个平台.这款游戏是基于&l ...
- Android Activity生命周期详讲
管理 Activity 生命周期 通过实现回调方法管理 Activity 的生命周期对开发强大而又灵活的应用至关重要. Activity 的生命周期会直接受到 Activity 与其他 Activit ...
- socket编程中客户端常用函数 以及简单实现
1 常用函数 1.1 connect() int connect(int sockfd, const struct sockaddr *servaddr, socklen_taddrlen); 客 ...
- Mac下的快速回到桌面快捷方式
今天突然发现一个Mac下快速回到桌面的快捷方式. command+F3 快速回到桌面. 如果想增加动画效果,快捷键是: command+shift+F3 这个功能虽然小,但是确实非常实用啊!
- Java基础知识学习(七)
线程(续) 线程同步 当两个或两个以上的线程需要共享资源,它们需要某种方法来确定资源在某一刻仅被一个线程占用.达到此目的的过程叫做同步(synchronization) 可以用两种方法同步化代码.两者 ...
- C#实现函数默认值和C#4.0实现默认值
static void Main(string[] args) { SayHello(); SayHello("侯志强"); Console.ReadKey(); } C#.0实现 ...