转载自:http://www.94cto.com/index/Article/content/id/59973.html

1.引例:

今天在做了一道关于有符号数和无符号数相互转换及其左移/右移的问题,被它们之间的转换原理和位移原理搞得头大了。真的很后悔本科的时候没有认真学习《计算机组成原理》/《计算机操作系统》等计算机基础课程。以下是我根据相关知识回顾和整理的材料,如有和某某的文章有雷同之处,请勿见怪。另外也希望看到这篇文章的同志们能够有所收获吧。

#include <cstdio>
#include <iostream>
using namespace std; int main()
{
unsigned short int ui;
signed short int si;
ui = (unsigned short int)0x8000u;
si = (signed short int)0x8000;
printf("ui = %u\n",ui);
printf("si = %d\n",si);
ui = ui>>1;
si = si>>1;
printf("ui = %u\n",ui);
printf("si = %d\n",si);
cout<<"------------------------------"<<endl; ui = (unsigned short int)0x8000u;
si = (signed short int)0x8000;
printf("%u\n",ui);
printf("%d\n",si);
ui = ((signed short int)ui>>1);
si = ((unsigned short int)si>>1);
printf("%u\n",ui);
printf("%d\n",si);
cout<<"------------------------------"<<endl; ui = (unsigned short int)0x8000u;
si = (signed short int)0x8000;
printf("%u\n",ui);
printf("%d\n",si);
ui = ui<<1;
si = si<<1;
printf("%u\n",ui);
printf("%d\n",si);
cout<<"-------------------------------"<<endl; ui = (unsigned short int)0x8000u;
si = (signed short int)0x8000;
printf("%u\n",ui);
printf("%d\n",si);
ui = ((signed short int)ui<<1);
si =((unsigned short int)si<<1);
printf("%u\n",ui);
printf("%d\n",si);
return 0;
}

显示结果:

ui = 32768
si = -32768
ui = 16384
si = -16384
------------------------------
32768
-32768
49152
16384
------------------------------
32768
-32768
0
0
-------------------------------
32768
-32768
0
0

2.概念
 在计算机中,可以区分正负类型的数,成为“有符号数”(signed);无正负类型的数(只有整数类型),成为“无符号数”(unsigned)。简明的说,无符号说就是其所有的位数都用来表示数值的大小,有符号数除最高位来表示数值的正负外(0表示正数;1表示负数),其余各位用来表示数值的大小。举个例子说明一下:十机制数 正数255  二进制表达形式:1111 1111

十机制数 负数-1     二进制表达形式:1111 1111

可见-1的二进制的最高位为红色的1,可是为什么其表达形式为1111 1111而不是1000 0001呢?这就关于任何数在计算机内是以补码形式存储问题。下面会介绍的,在此先不详细说明了。

3.存储范围

从前面的介绍可以知道,由于有符号数的最高位被拿来用作符号位,所以它所能够表达的最大数值要小于无符号数所能够表达的最大数值。还是举个例子来说明一下吧:

无符号数:1111 1111 十进制值:255

有符号数:0111 1111 十进制值:127

这是有人可能会提出这样的疑问:有符号数所能够表达的数值范围会不会小于无符号数所能够表达的数值范围呢?

呵呵,答案是否定的!虽然有符号数在表达最大值上的能力减弱了,但是它能够表达负数。负数的个数可以弥补其不足。来让我们比较一下:

一个字节的无符号数的表达数值范围是:[0,255]

一个字节的有符号数的表达数值范围是:[-128,0),[0,127]

可见它们都能够表示256个数。

4.各种码(原码/反码/补码)

有些人也许会这样认为"-1"(双字节)在计算机中的表达形式为1000 0000 0000 0001,可是实际上不是的。计算机是以其补码的形式进行表达的,即“-1”(双字节)的表达形式是1111 1111 1111 1111。

说一下各种码的概念吧。

原码:一个整数,按照绝对值的大小转换成二进制数,最高位为符号位。

反码:将原码除最高位(符号位)外,其余各位按位取反,所得到的二进制码。正数的反码为原码。

补码:反码最低位加1即为补码。

关于负数的补码求法说明一下,先得到其反码,之后将反码加1即可。有些大神根据其原码,闭眼即得,这种能力需要修炼一下啊。

这时有些人可能会说,为什么要引入补码的形式呢?直接按照原码存储不就省事很多吗?嘿嘿,要记住,有些事情并不是你想省事就能省事的。好了来欣赏一下补码的优势吧。

计算机的带符号数用补码表示的优点:

1负数的补码与对应正数的补码之间的转换可以用同一种方法-求补运算完成,可以简化硬件。 2 可将减法变为加法,这样减法就可以用加法器进行计算了。 3 两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。

心算求补(大神求补算法):

从最低位开始至找到的第一个1均不变,符号位不变,这之间的各位“求反”(0变1;1变0)。

原码:1010 1001  补码:1101 0111.

5.有符号数与无符号数的相互转换

无符号整数和有符号整数之间进行强制类型转换时,位模式不改变。

有符号数转换为无符号数时,负数转换为大的正数,相当于在原值上加上2的n次方,而正数保持不变。

无符号数转换为有符号数时,对于小的数将保持原值,对于大的数将转换为负数,相当于原值减去2的n次方。

当表达式中存在有符号数和无符号数类型时,所有的操作都自动转换为无符号类型。可见无符号数的运算优先级高于有符号数。

unsigned int a = 20;
signed int b = -130;

运算一下结果是 b>a 。

6.转换大餐

有符号数的转换

原类型 目标类型 转换方法
 char

short

符号位扩展
char long 符号位扩展
char unsigned char 最高符号位失去位意义,变为数据位
char unsigned short 符号位扩展到short;然后从short转到unsigned short
char unsigned long 符号位扩展到long;然后从long转换到unsigned long
char float 符号位扩展到long;然后从long转到float
char double 符号位扩展到long;然后从long转换到double
char long double 符号位扩展到long;然后从long转换到long double
short char 保留低位字节
short long 符号位扩展
short unsigned char 保留低位字节
short unsigned short

最高为失去意义,变为数据位

short unsigned long 符号位扩展到long;然后从long转到unsigned long
short float 符号位扩展到long;然后从long转到float
short double 符号位扩展到long;然后从long转到double
short long double 符号位扩展到long;然后从long转换到long double
long char 保留低位字节
long short 保留低位字节
long unsigned char 保留低位字节
long unsigned short 保留低位字节
long unsigned long 最高为失去意义,变为数据位
long float 使用单精度浮点数表示,可能失去精度
long double 使用单精度浮点数表示,可能失去精度
long long double 使用单精度浮点数表示,可能失去精度

无符号数的转换

原类型 目标类型 转换方法
unsigned char char 最高为作符号位
unsigned char short 0扩展
unsigned char long 0扩展
unsigned char unsigned short 0扩展
unsigned char unsigned long 0扩展
unsigned char float 转换到long;然后从long转换到float
unsigned char double 转换到long;然后从long转换到double
unsigned char long double 转换到long;然后从long转换到long double
unsigned short char 保留低位字节
unsigned short short 最高为作符号位
unsigned short long 0扩展
unsigned short unsigned char 保留低位字节
unsigned short unsigned long 0扩展
unsigned short float 转换到long;然后从long转换到float
unsigned short double 转换到long;然后从long转换到double
unsigned long long double 转换到long;然后从long转换到long double
unsigned long char 保留低位字节
unsigned long short 保留低位字节
unsigned long long 最高位作符号位
unsigned long unsigned char 保留低位字节
unsigned long unsigned short 保留低位字节
unsigned long float 转换到long;然后从long转换到float
unsigned long double 直接转换到double
unsigned long long double 转换到long;然后从long转换到long double

7.各种数据类型所占字节

32位平台下:

关于有符号数和无符号数的转换 - C/C++的更多相关文章

  1. C语言基础(5)-有符号数、无符号数、printf、大小端对齐

    1.有符号数和无符号数 有符号数就是最高位为符号位,0代表正数,1代表负数 无符号数最高位不是符号位,而就是数的一部分而已. 1011 1111 0000 1111 1111 0000 1011 10 ...

  2. 深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字

    上一篇博客我们讲解了计算机中整数的表示,包括无符号编码和补码编码,以及它们之间的互相转换,个人觉得那是非常重要的知识要点.这篇博客我们将介绍C语言中的有符号数和无符号数以及扩展和截断数字. 1.C语言 ...

  3. C语言中 有符号数、无符号数、整数溢出 (转)

    #include<stdio.h> void main() { int l=-1; unsigned int c=135; printf("%u\n",l+c); } ...

  4. 有符号数和无符号数------c++程序设计原理与实践(进阶篇)

    有符号数与无符号数的程序设计原则: 当需要表示数值时,使用有符号数(如 int). 当需要表示位集合时,使用无符号数(如unsigned int). 有符号数和无符号数混合运算有可能会带来灾难性的后果 ...

  5. java 理解有符号数和无符号数

    转至:http://jinguo.iteye.com/blog/212049 理解有符号数和无符号数负数在计算机中如何表示呢? 这一点,你可能听过两种不同的回答. 一种是教科书,它会告诉你:计算机用“ ...

  6. c++ 常量/有符号数和无符号数

    一.宏定义 #define 和常量 const 1. const关键字 const是constant的简写,只要一个变量前面用const来修饰,就意味着该变量里的数据可以被访问,不能被修改.也就是说c ...

  7. Mysql中有符号数和无符号数的区别

    1原文地址:https://blog.csdn.net/s78365126/article/details/85048882 2可以手写sql验证一下 3mysql无符号和有符号的区别无符号unsig ...

  8. Qt之C语言有符号数与无符号数运算

    以32位的stm32f4为例: 1.  uint32_t t_int_k = 239773, t_int_km1 = 4294859707; 则t_int_k - t_int_km1 > 0; ...

  9. C语言迷题:有符号数与无符号数的问题(转)

    https://my.oschina.net/kelvinfang/blog/134725

随机推荐

  1. 微信小程序实现搜索关键词高亮

    目录 1,前言 2,思路 3,代码逻辑 1,前言 项目中碰到一个需求,搜索数据并且关键词要高亮显示,接到需求,马上开干.先上效果图.源码已经做成了小程序代码片段,放入了GitHub了,文章底部有源码链 ...

  2. [状压DP]炮兵阵地

    炮 兵 阵 地 炮兵阵地 炮兵阵地 题目描述 司令部的将军们打算在 N ∗ M N*M N∗M的网格地图上部署他们的炮兵部队.一个 N ∗ M N*M N∗M的地图由 N N N行 M M M列组成, ...

  3. 【论文笔记】Learning Fashion Compatibility with Bidirectional LSTMs

    论文:<Learning Fashion Compatibility with Bidirectional LSTMs> 论文地址:https://arxiv.org/abs/1707.0 ...

  4. Leedcode算法专题训练(字符串)

    4. 两个字符串包含的字符是否完全相同 242. Valid Anagram (Easy) Leetcode / 力扣 可以用 HashMap 来映射字符与出现次数,然后比较两个字符串出现的字符数量是 ...

  5. 黑马架构师v2.5.1 (codeUtil)使用注意事项

    资源 1.资料里的codeutil软件有问题,使用时部分类和接口文件名后有一串日期数字等.码云的没问题 2.生成代码后zookeeper的IP改为本机的

  6. 自动化kolla-ansible部署ubuntu20.04+openstack-victoria单机

    自动化kolla-ansible部署ubuntu20.04+openstack-victoria单机 欢迎加QQ群:1026880196 进行交流学习 一. 环境信息 1. 硬件信息 型号:Dell ...

  7. 一起来看Java设计思想之23种设计模式

    目录 怎么使用设计模式 23种设计模式 创建型模式 结构型模式 行为型模式 总结 怎么使用设计模式 为什么要使用设计模式? 编写代码,写接口.写类.写方法 用设计模式做设计的作用是什么? 指导.规定如 ...

  8. Day02_15_方法重载

    方法重载 1.什么是方法重载? * 方法重载又被称为 OverLoad,是指在同一个类中,具有相同方法名的不同方法,各个方法虽然方法名相同,但是各自的形式参数不同. 2.什么时候考虑使用方法重载? * ...

  9. jira 改变issue状态触发jenkins构建/发布

    目录 jira中issue状态的改变触发Jenkins构建 jira中定制新的workflow,作为jenkins发布使用流程 大家可以参考我的这个workflow 设置workflow 使用Tran ...

  10. 经典论文系列| 实例分割中的新范式-SOLO

    前言: 这是实例分割中的一篇经典论文,以往的实例分割模型都比较复杂,这篇论文提出了一个简单且直接的实例分割模型,如何设计这种简单直接的模型且要达到一定的精度往往会存在一些困难,论文中有很多思路或思想值 ...