《编写高质量代码:改善c程序代码的125个建议》——建议2:防止整数类型产生回绕与溢出

简介:

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

建议2:防止整数类型产生回绕与溢出

到C99为止,C语言为我们提供了12个相关的数据类型关键字来表达各种数据类型。如表1-2所示,K&R C提供了7个,C89/C90新增了2个,C99新增了3个。


<a href=https://yqfile.alicdn.com/2c575593fb8fbf685cadc4bce887b4fa480c6a62.png" >

整型是C语言最基本的数据类型,它以二进制编码的方式进行存储,具体可以包括字符、短整型、整型和长整型等。例如,整数2的二进制表示为10,它在8位与32位的操作系统中存储方式如图1-3所示。


<a href=https://yqfile.alicdn.com/2fcca96a5d805b2b0d815980e34c637ab10ef7f2.png" >

虽然在计算机中整数是以二进制编码方式进行存储的,但为了便于表达,有时候又会用十六进制编码方式表示(例如,在32位操作系统下,整数2的十六进制编码方式为0x00000002),二进制和十六进制之间能够很方便地进行转换。
与此同时,整数类型又可分为有符号(signed)和无符号(unsigned)两种类型,limits.h文件定义了整型数据类型的表达值范围。在GCC 4.8.3中,limits.h文件定义如下:
/*
 *    ISO C99 Standard: 7.10/5.2.4.2.1 Sizes of integer types <limits.h>
 */

#ifndef _LIBC_LIMITS_H_
#define _LIBC_LIMITS_H_    1

#include <features.h>


/* Maximum length of any multibyte character in any locale.
   We define this value here since the gcc header does not define
   the correct value.  */
#define MB_LEN_MAX 16


/* If we are not using GNU CC we have to define all the symbols ourself.
   Otherwise use gcc's definitions (see below).  */
#if !defined __GNUC__ || __GNUC__ < 2

/* We only protect from multiple inclusion here, because all the other 
   #include's protect themselves, and in GCC 2 we may #include_next through 
   multiple copies of this file before we get to GCC's.  */
# ifndef _LIMITS_H
#  define _LIMITS_H 1

#include <bits/wordsize.h>

/* We don't have #include_next.
   Define ANSI <limits.h> for standard 32-bit words.  */

/* These assume 8-bit `char's, 16-bit `short int's,
   and 32-bit `int's and `long int's.  */

/* Number of bits in a `char'.    */
#  define CHAR_BIT 8

/* Minimum and maximum values a `signed char' can hold.  */
#  define SCHAR_MIN    (-128)
#  define SCHAR_MAX    127

/* Maximum value an `unsigned char' can hold.  (Minimum is 0.)  */
#  define UCHAR_MAX    255

/* Minimum and maximum values a `char' can hold.  */
#  ifdef __CHAR_UNSIGNED__
#   define CHAR_MIN 0
#   define CHAR_MAX    UCHAR_MAX
#  else
#   define CHAR_MIN    SCHAR_MIN
#   define CHAR_MAX    SCHAR_MAX
#  endif

/* Minimum and maximum values a `signed short int' can hold.  */
#  define SHRT_MIN    (-32768)
#  define SHRT_MAX    32767

/* Maximum value an `unsigned short int' can hold.  (Minimum is 0.)  */
#  define USHRT_MAX    65535

/* Minimum and maximum values a `signed int' can hold.  */
#  define INT_MIN    (-INT_MAX - 1)
#  define INT_MAX    2147483647

/* Maximum value an `unsigned int' can hold.  (Minimum is 0.)  */
#  define UINT_MAX    4294967295U

/* Minimum and maximum values a `signed long int' can hold.  */
#  if __WORDSIZE == 64
#   define LONG_MAX    9223372036854775807L
#  else
#   define LONG_MAX    2147483647L
#  endif
#  define LONG_MIN    (-LONG_MAX - 1L)

/* Maximum value an `unsigned long int' can hold.  (Minimum is 0.)  */
#  if __WORDSIZE == 64
#   define ULONG_MAX    18446744073709551615UL
#  else
#   define ULONG_MAX    4294967295UL
#  endif

#  ifdef __USE_ISOC99

/* Minimum and maximum values a `signed long long int' can hold.  */
#   define LLONG_MAX    9223372036854775807LL
#   define LLONG_MIN    (-LLONG_MAX - 1LL)

/* Maximum value an `unsigned long long int' can hold.  (Minimum is 0.)  */
#   define ULLONG_MAX    18446744073709551615ULL

#  endif /* ISO C99 */

# endif    /* limits.h  */
#endif    /* GCC 2.  */

#endif    /* !_LIBC_LIMITS_H_ */

/* The <limits.h> files in some gcc versions don't define LLONG_MIN,LLONG_MAX,
   and ULLONG_MAX.  Instead only the values gcc defined for ages are   available. */
#if defined __USE_ISOC99 && defined __GNUC__
# ifndef LLONG_MIN
#  define LLONG_MIN    (-LLONG_MAX-1)
# endif
# ifndef LLONG_MAX
#  define LLONG_MAX    __LONG_LONG_MAX__
# endif
# ifndef ULLONG_MAX
#  define ULLONG_MAX    (LLONG_MAX * 2ULL + 1)
# endif
#endif


<a href=https://yqfile.alicdn.com/42f82c32e528e68de88131263ce8751e6662f54a.png" >

简单地讲,有符号和无符号整数间的区别在于怎样解释整数的最高位。如果定义一个有符号整数,则C编译程序生成的代码认为该数最高位是符号标志:符号标志为0,则该数为正;符号标志为1,则该数为负。
负数采用2的补码的形式来表示,即对原码各位求反(符号位除外),再将求反的结果加1,最后将符号位设置为1。例如,在32位操作系统中,有符号整数-2的存储方法如下。
第一步:取绝对值2的二进制编码。
00000000 00000000 00000000 00000010

第二步:求反(符号位除外)。

01111111 11111111 11111111 11111101

第三步:将求反的结果加1。

01111111 11111111 11111111 11111110

第四步:将符号位设置为1。

11111111 11111111 11111111 11111110

因此,有符号整数-2的二进制编码为11111111 11111111 11111111 11111110,十六进制编码为0xFFFFFFFE。
最后还需要说明的是,当类型修饰符被自身使用时(即它不在基本类型之前时),假定其为int型。也就是说,表1-4的两种类型是等效的。


77a8c9ace3cd575b25fb13b395b8426d0e80b2af
相关文章
|
传感器 机器学习/深度学习 人工智能
【AI 现况分析】AI 如何落地到机器人技术上?
【1月更文挑战第27天】【AI 现况分析】AI 如何落地到机器人技术上?
|
数据可视化 前端开发 测试技术
软件需求分析实践——需求拆分| 学习笔记
快速学习软件需求分析实践——需求拆分
软件需求分析实践——需求拆分| 学习笔记
|
1月前
|
Prometheus 监控 Cloud Native
78_资源监控:NVIDIA-SMI进阶
在大语言模型(LLM)训练和推理过程中,GPU资源的高效监控和管理至关重要。随着模型规模的不断增长和计算需求的提升,如何精确监控GPU利用率、及时发现性能瓶颈并进行优化,成为AI研究人员和工程师面临的重要挑战。NVIDIA-SMI作为NVIDIA官方提供的GPU监控工具,提供了丰富的功能来监控和管理GPU资源。本文将深入探讨NVIDIA-SMI的进阶使用方法,以及如何利用其与其他工具结合构建高效的GPU利用率可视化监控系统。
|
8月前
|
XML 人工智能 数据可视化
ReasonGraph:别让AI成黑箱!这个开源工具把大模型的脑回路画给你看
ReasonGraph是一款开源的可视化分析工具,能将大语言模型的复杂推理过程转化为直观图表,支持50+主流模型和多种推理方法,帮助开发者快速理解AI思考逻辑并优化模型表现。
448 0
|
9月前
|
存储 安全 文件存储
剪切未粘贴成功的文件不见了怎么找回来?
你正在移动文件,使用“剪切”命令准备粘贴到新位置,却发现粘贴操作失败,文件却消失了。这个时候,你可能会觉得非常沮丧,因为你以为文件已经消失得无影无踪。然而,不必过于担心,这种情况其实是可以恢复的。在本文中,我们将介绍几种有效的方式,帮助你找回那些“失踪”的文件,让它们重回你的电脑。
|
XML JSON Java
Android App网络通信中通过okhttp调用HTTP接口讲解及实战(包括GET、表单格式POST、JSON格式POST 附源码)
Android App网络通信中通过okhttp调用HTTP接口讲解及实战(包括GET、表单格式POST、JSON格式POST 附源码)
2009 0
|
编解码 iOS开发 Windows
B站电脑版,原来还隐藏着这个白嫖福利|Windows如何打开heic图片?
B站电脑版,原来还隐藏着这个白嫖福利|Windows如何打开heic图片?
|
Ubuntu 安全 搜索推荐
Linux Ubuntu 桌面环境概览
Ubuntu,在开源领域如同璀璨明星,以其卓越的桌面环境和用户体验赢得全球用户的心。采用优雅且功能丰富的GNOME桌面,Ubuntu界面简洁现代,提供直观易用的操作体验。无论是文件管理还是系统设置,图形界面让一切变得轻松。此外,高度可定制化特性让桌面成为个性展示的舞台,集成丰富应用满足多样化需求。背后强大的社区支持确保用户获得及时帮助,共享开源精神。
481 0
|
机器学习/深度学习 人工智能 监控
论文介绍:Masked-attention Mask Transformer (Mask2Former)——通用图像分割的新架构
【5月更文挑战第24天】Mask2Former,一种新型的图像分割架构,采用遮蔽注意力机制聚焦局部特征,提升模型收敛速度和性能,在COCO、Cityscapes等数据集上刷新记录。其元架构结合背景特征提取器、像素解码器和Transformer解码器,实现高效训练和性能提升。尽管在处理小对象和泛化能力上仍有局限,但Mask2Former为通用图像分割开辟了新路径。[链接](https://arxiv.org/abs/2112.01527)
1030 5
|
设计模式 负载均衡 算法
C/C++发布-订阅者模式世界:揭秘高效编程的秘诀
C/C++发布-订阅者模式世界:揭秘高效编程的秘诀
710 1