转载自: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. Angle Beats Gym - 102361A

    题目链接:https://vjudge.net/problem/Gym-102361A 题意:给定N个点,q次询问每次询问给一个点,问在N个点中取2个和给定点最多可以组成几个直角三角形. 思路:htt ...

  2. ch2_8_4求解投骰子游戏问题

    思路:递推.到第n步可以从第0步走n步到第n步,从第1步走n-1步到第n步... ...依次类推,=> f(n)=f(0)+f(1)+...+f(n-1) import java.util.Sc ...

  3. 全网最详细的Linux命令系列-rm命令

    今天学习一下linux中删除文件和目录的命令: rm命令.rm是常用的命令,该命令的功能为删除一个目录中的一个或多个文件或目录,它也可以将某个目录及其下的所有文件及子目录均删除.对于链接文件,只是删除 ...

  4. 「HTML+CSS」--自定义加载动画【009】

    前言 Hello!小伙伴! 首先非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 哈哈 自我介绍一下 昵称:海轰 标签:程序猿一只|C++选手|学生 简介:因C语言结识编程,随后转入计算机 ...

  5. H5 端 rem 适配方案与 viewport 适配

    H5 端 rem 适配方案与 viewport 适配 rem rem 是 CSS3 新增的一个相对单位(root em,根 em) 只根据当前页面 HTML 页面的 font-size 设置,如果根目 ...

  6. 754. Reach a Number

    You are standing at position 0 on an infinite number line. There is a goal at position target. On ea ...

  7. Nginx篇

    1 基本操作命令 先CD到nginx.exe目录 启动nginx服务 nginx start nginx 优雅停止nginx,有连接时会等连接请求完成再杀死worker进程 nginx -s quit ...

  8. Linux安装MySQL8高版本压缩包(通用)

    前言 前段时间领导让我部署测试环境,希望安装高版本的MySQL,过程遇到很多问题,特此记录帮助迷失的人们 下载 MySQL官方下载地址:https://dev.mysql.com/downloads/ ...

  9. 【ElasticSearch】ElasticSearch集群扫盲

    Cluster 集群 ⼀个 Elasticsearch 集群由⼀个或多个节点(Node)组成,每个集群都有⼀个共同的集群名称作为标识.   Node节点 ⼀个 Elasticsearch 实例即⼀个 ...

  10. dedecms发布文章排序按发布时间,不是更新时间

    织梦DEDECMS5.7这个版本存在一个问题,修改文章的同时也修改了文章的发布时间,这种情况下,如果我们调用最新文章时使用按"发布日期排序",就会打乱原来我们网站上的文章的顺序. ...