转载自: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. 根据数据渲染DOM树形菜单——中途感想

    根据数据渲染DOM树形菜单,这个需求做了几天了.一开始觉得用while也可以实现一层一层查找数据,但后来发现while还是做不到,因为我查找这个动作必须有进入有出来然后进入下一个条目,但while只能 ...

  2. Mysql之索引选择及优化

    索引模型 哈希表 适用于只有等值查询的场景,Memory引擎默认索引 InnoDB支持自适应哈希索引,不可干预,由引擎自行决定是否创建 有序数组:在等值查询和范围查询场景中的性能都非常优秀,但插入和删 ...

  3. python函数之有参装饰器

    一.为什么要有有参装饰器? 来看之前的无参装饰器 # 无参装饰器 def outter(func): def wrapper(*args,**kwargs): start = time.time() ...

  4. CentOS7 搭建 K8S 环境

    前期准备 环境规划 K8S 与Docker兼容问题 k8s v1.18.0 => Docker v18.x k8s v1.19.0 => Docker v19.x 软件 版本 Linux操 ...

  5. [模拟]P1046 陶陶摘苹果

    陶陶摘苹果 ## 题目描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试 ...

  6. Dynamics CRM9.0更新了Chrome后菜单按钮变形

    前段时间Chorme更新后Dynamics CRM9.0的系统菜单样式变的很难看 具体修改方法如下: 找到Dynamics CRM安装目录C:\Program Files\Microsoft Dyna ...

  7. 【ProLog - 4.0 List】

    [简介] 列表是Prolog编程中常用的一种重要的递归数据结构 列表是一个有限的元素序列 实例: 所有Prolog术语都可以是列表的元素,一个非空的List应该含有两个元素:头元素(Head)和尾元素 ...

  8. 字体图标库 iconfont、iconmoon 的维护管理与使用探索

    字体图标库的使用 这是之前留下的博客,由于一堆博客没写完,本周周末做了个补充,可能内容上会有点不太斜街,请见谅... 本文大部分内容是自己结合过往经验探索总结的字体图标维护方式 iconfont-阿里 ...

  9. 自动化kolla-ansible部署ubuntu20.04+openstack-victoria之镜像上传-11

    自动化kolla-ansible部署ubuntu20.04+openstack-victoria之镜像上传-11 欢迎加QQ群:1026880196 进行交流学习 镜像上传 #controller1 ...

  10. Molar mass UVA - 1586

    ​ An organic compound is any member of a large class of chemical compounds whose molecules contain c ...