关于有符号数和无符号数的转换 - C/C++
转载自: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++的更多相关文章
- C语言基础(5)-有符号数、无符号数、printf、大小端对齐
1.有符号数和无符号数 有符号数就是最高位为符号位,0代表正数,1代表负数 无符号数最高位不是符号位,而就是数的一部分而已. 1011 1111 0000 1111 1111 0000 1011 10 ...
- 深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字
上一篇博客我们讲解了计算机中整数的表示,包括无符号编码和补码编码,以及它们之间的互相转换,个人觉得那是非常重要的知识要点.这篇博客我们将介绍C语言中的有符号数和无符号数以及扩展和截断数字. 1.C语言 ...
- C语言中 有符号数、无符号数、整数溢出 (转)
#include<stdio.h> void main() { int l=-1; unsigned int c=135; printf("%u\n",l+c); } ...
- 有符号数和无符号数------c++程序设计原理与实践(进阶篇)
有符号数与无符号数的程序设计原则: 当需要表示数值时,使用有符号数(如 int). 当需要表示位集合时,使用无符号数(如unsigned int). 有符号数和无符号数混合运算有可能会带来灾难性的后果 ...
- java 理解有符号数和无符号数
转至:http://jinguo.iteye.com/blog/212049 理解有符号数和无符号数负数在计算机中如何表示呢? 这一点,你可能听过两种不同的回答. 一种是教科书,它会告诉你:计算机用“ ...
- c++ 常量/有符号数和无符号数
一.宏定义 #define 和常量 const 1. const关键字 const是constant的简写,只要一个变量前面用const来修饰,就意味着该变量里的数据可以被访问,不能被修改.也就是说c ...
- Mysql中有符号数和无符号数的区别
1原文地址:https://blog.csdn.net/s78365126/article/details/85048882 2可以手写sql验证一下 3mysql无符号和有符号的区别无符号unsig ...
- Qt之C语言有符号数与无符号数运算
以32位的stm32f4为例: 1. uint32_t t_int_k = 239773, t_int_km1 = 4294859707; 则t_int_k - t_int_km1 > 0; ...
- C语言迷题:有符号数与无符号数的问题(转)
https://my.oschina.net/kelvinfang/blog/134725
随机推荐
- io流(File类)
File类 创建一个file类(没有无参构造)的对象,并与文件进行关联 用File类来操作文件,代码如下: package com.bjsxt.test01; import java.io.File; ...
- 【LeetCode】4. Median of Two Sorted Arrays(思维)
[题意] 给两个有序数组,寻找两个数组组成后的中位数,要求时间复杂度为O(log(n+m)). [题解] 感觉这道题想法非常妙!! 假定原数组为a,b,数组长度为lena,lenb. 那么中位数一定是 ...
- lms框架即将发布第一个版本了
lms微服务框架介绍 LMS框架旨在帮助开发者在.net平台下,通过简单的配置和代码即可快速的使用微服务进行开发. LMS通过.net框架的主机托管应用,内部通过dotnetty/SpanNetty实 ...
- Androi Studio 之 LinearLayout
LinearLayout •常用属性 •注意事项 当 android:orientation="vertical" 时, 只有水平方向的设置才起作用,垂直方向的设置不起作用 a ...
- Spring笔记(三)
Spring AOP 一.AOP(概念) 1. 什么是AOP 面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合度降低,提高程序的可重用性,同时提高了 ...
- 阿里妈妈Java后端 社招5面(Offer已拿)
最近由于个人原因, 由于前面两面的时间过去的有点久了,只能根据记忆大概写些记得问题. 阿里妈妈1面 40mins(2021-02-22) 1. 能简单介绍下自己和自己做的项目吗? 2. 关于项目的 ...
- 2021年春软件工程"助教团队"成员介绍
2021年春软件工程 助教团队 成员介绍 项目 内容 这个作业属于那个课程 2021春季学期软件工程(罗杰.任健) 这个作业的要求在哪里 团队介绍 姓名 照片 个人介绍 分工 刘Q 本团队的PM,和助 ...
- 算法很美,听我讲完这些Java经典算法包你爱上她
大家好,我是小羽. 对于编程来说的话,只有掌握了算法才是了解了编程的灵魂,算法对于新手来说的话,属实有点难度,但是以后想有更好的发展,得到更好的进阶的话,对算法进行系统的学习是重中之重的. 对于 Ja ...
- SSH 教程 ——阮一峰
SSH 教程 --阮一峰 文章出处 SSH 基本知识 SSH(Secure Shell 的缩写)是一种网络协议,用于加密两台计算机之间的通信,并且支持各种身份验证机制.实务中,它主要用于保证远程登录和 ...
- 干掉 Feign,Spring Cloud Square 组件发布
Spring Cloud Square 是什么 谈起 Spring Cloud 生态大家一定对 Feign 不陌生,如下图所示,Feign 可以把底层(okhttp.httpclient)Rest 的 ...