博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《编写高质量代码:改善c程序代码的125个建议》——建议4-1:整数转换为新类型时必须做范围检查...
阅读量:5989 次
发布时间:2019-06-20

本文共 3822 字,大约阅读时间需要 12 分钟。

本节书摘来自华章计算机《编写高质量代码:改善c程序代码的125个建议》一书中的第1章,建议4-1,作者:马 伟 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

建议4-1:整数转换为新类型时必须做范围检查

关于整数类型数据的转换原则,在C99的6.3.1.3节中做了非常重要的阐述,其表达的主要意思如下:

当我们将一个整数类型的数据转换成除_Bool类型之外的另一个整数类型时,如果这个值可以被新的整数类型所表示,那么它就不会被修改,可以正确转换;如果所转换的新类型是无符号的,那么这个值就会反复加上或减去这个新类型可以表示的最大值加1,直到这个值位于这种新类型的范围之内;如果所转换的新类型是有符号的,并且这个值无法用新类型表示,那么它的结果是由编译器定义的。
因此,为了保证整型数据转换时不会发生丢失或错误解释数据的情况,我们必须做一定的范围检查,以保证要转换的数据的值在新类型的取值范围之内。而在头文件limits.h中就定义了相关整型数据的取值范围,例如,在VC++ 2010中定义的limits.h部分代码如下所示:

#define CHAR_BIT      8             /* number of bits in a char */#define SCHAR_MIN   (-128)          /* minimum signed char value */#define SCHAR_MAX     127          /* maximum signed char value */#define UCHAR_MAX     0xff         /* maximum unsigned char value */#ifndef _CHAR_UNSIGNED#define CHAR_MIN    SCHAR_MIN        /* mimimum char value */#define CHAR_MAX    SCHAR_MAX        /* maximum char value */#else#define CHAR_MIN      0#define CHAR_MAX    UCHAR_MAX#endif  /* _CHAR_UNSIGNED */#define MB_LEN_MAX   5             /* max. # bytes in multibyte char */#define SHRT_MIN    (-32768)        /* minimum (signed) short value */#define SHRT_MAX      32767        /* maximum (signed) short value */#define USHRT_MAX     0xffff        /* maximum unsigned short value */#define INT_MIN (-2147483647 - 1)    /* minimum (signed) int value */#define INT_MAX     2147483647        /* maximum (signed) int value */#define UINT_MAX    0xffffffff        /* maximum unsigned int value */#define LONG_MIN (-2147483647L - 1)    /*minimum(signed) long value */#define LONG_MAX    2147483647L        /* maximum (signed) long value */#define ULONG_MAX   0xffffffffUL        /* maximum unsigned long value */#define LLONG_MAX   9223372036854775807i64    /* maximum signed                                                       long long int value */#define LLONG_MIN  (-9223372036854775807i64 - 1) /* minimum                                                    signed long long int value */#define ULLONG_MAX  0xffffffffffffffffui64    /* maximum unsigned                                                  long long int value */#define _I8_MIN    (-127i8 - 1)        /* minimum signed 8 bit value */#define _I8_MAX    127i8             /* maximum signed 8 bit value */#define _UI8_MAX   0xffui8            /* maximum unsigned 8 bit value */#define _I16_MIN  (-32767i16 - 1)    /* minimum signed 16 bit value */#define _I16_MAX   32767i16         /* maximum signed 16 bit value */#define _UI16_MAX  0xffffui16         /* maximum unsigned 16 bit value */#define _I32_MIN  (-2147483647i32 - 1)    /* minimum signed 32                                            bit value */#define _I32_MAX   2147483647i32        /* maximum signed 32 bit value */#define _UI32_MAX  0xffffffffui32    /*maximum unsigned 32 bit value*//* minimum signed 64 bit value */#define _I64_MIN    (-9223372036854775807i64 - 1)/* maximum signed 64 bit value */#define _I64_MAX      9223372036854775807i64/* maximum unsigned 64 bit value */#define _UI64_MAX     0xffffffffffffffffui64#if     _INTEGRAL_MAX_BITS >= 128/* minimum signed 128 bit value */#define _I128_MIN   (-170141183460469231731687303715884105727i128 - 1)/* maximum signed 128 bit value */#define _I128_MAX   170141183460469231731687303715884105727i128/* maximum unsigned 128 bit value */#define _UI128_MAX    0xffffffffffffffffffffffffffffffffui128#endif

举个例子,从一种无符号类型转换为一种有符号类型时,就可能发生数据的高位被截断而导致数据丢失,或者符号位丢失,所以在转换之前要对取值范围进行验证。下面的示例代码演示了如何从unsigned int类型转换为signed char类型:

unsigned int ui1=12345;signed char sc1;if(ui1>SCHAR_MAX){}else{    sc1=(signed)ui1;}

同样,如果将有符号类型转换为无符号类型,也必须进行取值范围的验证,示例代码如下所示:

signed int si1=-12345;unsigned int ui1= 0;if(si1<0||si1>UINT_MAX){}else{    ui1=(unsigned int)si1;}

在数据类型由“高级向低级”转换的时候,同样必须进行取值范围验证,示例代码如下所示:

long long int lli1=LLONG_MAX;int i1= 0;if(lli1
INT_MAX){}else{ i1=(int)lli1;}

转载地址:http://jcilx.baihongyu.com/

你可能感兴趣的文章
Spring4-内部bean
查看>>
程序员都应该知道的福利
查看>>
Outlook 2010上阅读模式的调整
查看>>
Windows脚本初探之VBScrip流程控制Select Case
查看>>
Java 多线程 线程的五种状态,线程 Sleep, Wait, notify, notifyAll
查看>>
C# 用params定义一维参数数组
查看>>
我的友情链接
查看>>
指针什么时候加*什么时候不需用加,分别代表什么含义
查看>>
平安城市安防监控工程案例
查看>>
网络学习(二十九)Windows Server 2003 WDS(Windows部署服务)
查看>>
XP与win7下power user共享文件的问题分析
查看>>
CCNA学习指南 第五章 下载
查看>>
小布老师的Oracle的安装教程
查看>>
第三天:XML&反射
查看>>
【好程序员笔记分享】C语言之scanf函数的其他用法和注意
查看>>
mysql建索引的几大原则
查看>>
esxi 5.0 的pxe安装
查看>>
mysql主主同步备份配置笔记
查看>>
nfs主从搭建详细教程
查看>>
saltstack日常应用
查看>>