1. 数据类型数值范围溢出

如标题所述,该错误出现的原因是由于变量的值超出该数据类型取值范围而导致的错误。

例题如下:

(IDE环境:C-Free,编译器为mingw5,如下图)

# include <iostream>

int main(){
short int a = ; // short int 取值范围:-32768~32768
short b = ; // short 是short int 的缩写
int c = a + b; // int 取值范围:-2147483648 ~2147483648
short d = a + b;
std::cout << c << ' ' << d << std::endl;
return ;
}

运行结果:

分析原因:a在内存中存储如下,其中第一位是符号位,0表示为正数,1表示负数。

0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0

那么 a + b 在内存如下:

1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

对于 “int c = a + b;” 由于c的取值范围为 -2147483648 ~2147483648,共32位,其中31位数据位,1位符号位,a + b 在c的取值范围内,其符号位依然是0,所以c的取值正常,为32768。

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

反观“short d = a + b;”其取值范围是 -32768~32768,共16位,其中15位数据位,1位符号位,d在内存中内容如下,其符号位为1,表示为负数,又因为数据在内存是以补码存储的,正数的原码反码补码相同,复数的补码是其反码加1,复数的补码的补码就是复数的原码。所以该内存存储形式的反码为 1111 1111 1111 1111,原码 1000 0000 0000 0000,换成10进制-32768(而不是-0).

 1 0  0 0 0 0 0 0 0 0 0 0 0 0

为了验证上述说明的正确性,在VS2015中重新运行,并打印结果的十六进制形式。

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <iostream>
#include <cstddef> int main() {
short int a = ;
short b = ;
int c = a + b;
short d = a + b;
printf("%d: Dec: %d; Hex: %x; size: %d;\n",c, c, c, sizeof(c));
printf("%d: Dec: %d; Hex: %x; size: %d\n",d, d, d, sizeof(d));
printf("%d: Dec: %d; Hex: %x; size: %d\n", d+, d + , d + , sizeof(d + )); system("pause");
return ;
}

结果如下:

对于c的结果,上述分析是正确的;而对于分析d的结果,似乎存在偏差。上述分析中对于d只有16位,而真正表示成十六进制时,却用到了32位,多分配了一倍的位数用来表示(但因为是short型,实际仍然只占2个字节),形成了向最高位借1(最低位是第0位).而为什么会形成这种问题,而不是上述分析那样,暂时不明白(手动标红,待解决)。(已解决,详情查看“【C++】常见易犯错误之数值类型取值溢出与截断(2)”)为了验证编译器为解决这种取值范围溢出,自动多分配1倍内存来表示,做下面实验。

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <iostream>
#include <iostream>
#include <cstddef> int main() {
system("color 3f");
short int a = ;
short b = ;
int c = a + b;
short d = a + b;
printf("%d: Dec: %d; Hex: %x; size: %d;\n",c, c, c, sizeof(c));
printf("%d: Dec: %d; Hex: %x; size: %d\n",d, d, d, sizeof(d));
printf("%d: Dec: %d; Hex: %x; size: %d\n", d+, d + , d + , sizeof(d + )); std::cout << "\n" << std::endl;
char f = ;
char g = ;
char h = f + g;
printf("%d: Dec: %d; Hex: %x; size: %d\n\n", h, h, h, sizeof(h));
system("pause");
return ;
}

结果:

char型取值范围-128~127,编译器为了解决这个问题,并非多分配一倍,在这里多分配了三倍内存表示,即内存中同样共用了32位来表示,但实际只占有1个字节。这是为什么呢,待解决,标红!

注:网上有这样一种负数的补码计算方式:模 - 该数的绝对值【1】

例:-1补码:1 0000 0000 - 0000 0001 = 1111 1111; 
       -3补码:1 0000 0000 - 0000 0011 = 1111 1101;

2.  数据类型数值范围截断

   发生截断的例子参考这里第(6)

参考文献

【1】-128在内存中如何存储
https://blog.csdn.net/magiclyj/article/details/75258195

【C++】常见易犯错误之数值类型取值溢出与截断(1)的更多相关文章

  1. 【C++】常见易犯错误之数值类型取值溢出与截断(3)

    0.  前言 本节是“[C++]常见易犯错误之数值类型取值溢出与截断(1)” 的补充,主要探讨浮点型的取值溢出. 1. 相关知识 (1) 浮点型数据取值范围如下: 单精度型 float 3.4 * 1 ...

  2. 【C++】常见易犯错误之数值类型取值溢出与截断(2)

    本节内容紧接上节,解决红色字体遗留问题.本节所有例子运行环境: win10 + VS2015 + X64 + debug 在上节例子中,查看变量 c .d .d+1 的类型. //// Console ...

  3. 编程中易犯错误汇总:一个综合案例.md

    # 11编程中易犯错误汇总:一个综合案例 在上一篇文章中,我们学习了如何区分好的代码与坏的代码,如何写好代码.所谓光说不练假把式,在这篇文章中,我们就做一件事——一起来写代码.首先,我会先列出问题,然 ...

  4. [golang 易犯错误] golang 局部变量初始化:=的陷阱

    我们知道,golang中局部变量初始化方法(使用“:=”创建并赋值),让我们在使用变量时很方便.但是,这也是易犯错误的地方之一.特别是这个初始化符还支持多个变量同时初始化,更特别的是它还支持原有变量赋 ...

  5. java代码书写易犯错误

    java代码书写易犯错误: 常见报错: 控制台报错: 找不到或无法加载主类 HelloWorld 原因: java.lang.NoClassDefFoundError: cn/itcast/day01 ...

  6. 带符号的char类型取值范围为什么是-128——127

    以前经常看到带符号的char类型取值范围是-128——127,今天突然想为什么不是-127——127,-128是怎么来的? 127好理解,char类型是8位,最高位是符号位,0正1负,所以011111 ...

  7. byte类型取值范围以及溢出具体解释

    例1: public class test { public static void main(String[] args) { byte a = 127 ; a = (byte)(a+3) ; Sy ...

  8. signed char类型取值范围计算

    在C语言程序中,给定一个类型,如何计算这个类型变量的取值范围呢?比如有一个字符型变量定义如下: signed char c: 这个字符变量c的取值范围是[-128,127],是计算出来的呢? 假设字符 ...

  9. Java开发者易犯错误Top10

    本文总结了Java开发者经常会犯的前十种错误列表. Top1. 数组转换为数组列表 将数组转换为数组列表,开发者经常会这样做: List<String> list = Arrays.asL ...

随机推荐

  1. 数学--数论--HDU 5382 GCD?LCM?(详细推导,不懂打我)

    Describtion First we define: (1) lcm(a,b), the least common multiple of two integers a and b, is the ...

  2. python(re 模块)

    1.re.match() 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none. group() 以str形式返回对象中match的元素 start() 返回 ...

  3. Nginx编译与安装

    我的系统是CentOS-7,Nginx的源码可以在官网下载,网址为:http://nginx.org/en/download.html,我下载了目前的最新版本nginx-1.9.3.tar.gz 下载 ...

  4. dfs+线段树 zhrt的数据结构课

    zhrt的数据结构课 这个题目我觉得是一个有一点点思维的dfs+线段树 虽然说看起来可以用树链剖分写,但是这个题目时间卡了树剖 因为之前用树剖一直在写这个,所以一直想的是区间更新,想dfs+线段树,有 ...

  5. 如何构建一个arm64 AArch64的Ubuntu rootfs

    文章目录 1 下载文件创建rootfs文件夹 2 安装qemu-user-static搭建arm64模拟环境 3 chroot 到 模拟arm64的文件系统下 4 安装基础的软件包 5 系统基础的修改 ...

  6. spring data jpa 多对多 ManyToMany

    环境搭建 源码地址:gitee:https://gitee.com/ytfs-dtx/JPA 导入依赖 <properties> <spring.version>5.2.5.R ...

  7. ApplicationInsights迁移国内躺的坑

    由于之前有段时间访问国际版的Application Insights实在是慢,而且又不是每个人都有梯子,然后国内版大概在去年(2019)六七月左右已经上线,想着也有一段时日了,要么就迁了吧. 然后实际 ...

  8. 【Poj-3693】Maximum repetition substring 后缀数组 连续重复子串

    POJ - 3693 题意 SPOJ - REPEATS的进阶版,在这题的基础上输出字典序最小的重复字串. 思路 跟上题一样,先求出最长的重复次数,在求的过程中顺便纪录最多次数可能的长度. 因为sa数 ...

  9. [hdu5375 Gray code]DP

    题意:给一个二进制码,其中有一些位上为'?',对每个问号确定是'0'还是'1',最后以它对应的格雷码来取数,第i位为1则取第i个数,求取得的数的和的最大值. 思路:二进制码B转换成格雷码G的方法是,G ...

  10. PHP带标签的字符串去除标签,计算字符串长度的两种格式,截取字符串

    $str = "<p>看地方撒地方<i>fdsafsdfsd</i><img src="/static/img/fdsf.jpg" ...