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>>;
si = si>>;
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>>);//先类型转换,再移位,
si = ((unsigned short int)si>>);
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<<;
si = si<<;
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<<);
si =((unsigned short int)si<<);
printf("%u\n",ui);
printf("%d\n",si);
return ;
}
运行结果

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位平台下:

ps:文中若有不当之处,请指出!
C++有符号和无符号数的转换的更多相关文章
- 关于有符号数和无符号数的转换 - C/C++
转载自:http://www.94cto.com/index/Article/content/id/59973.html 1.引例: 今天在做了一道关于有符号数和无符号数相互转换及其左移/右移的问题, ...
- JAVA byte有无符号数的转换
如果你只需要对英文文本的每个字节进行数据处理,则无需考虑有符号数和无符号数的转换问题: 但如果你需要对含有中文的文本进行字节处理,则可能需要考虑有无符号数的转换问题. 以下代码均为Java代码. 1. ...
- jni——如何转换有符号与无符号数
java数据结构默认均为有符号数,而通过jni转换到c/c++层,却不一定是有符号数. 如若在java中存储的即为无符号数,则在jni中可将jbyte直接进行类型转换. 若进行操作,则可在计算时,先将 ...
- 【C语言学习趣事】_33_关于C语言和C++语言中的取余数(求模)的计算_有符号和无符号数的相互转换问题
最近再次复习C++语言,用的教材是<C++ Primer>这本教材, 看到第二章的时候,里面有个问题困扰了我. 于是想上网查查怎么回事, 结果看了很久都没有得到一个满意的答案. 书上有这么 ...
- c语言中为什么左移不分符号数无符号数,而右移分呢??
因为在C语言标准中,只规定了无符号数的移位操作是采用逻辑移位(即左移.右移都是使用的逻辑左移和逻辑右移).而对于有符号数,其左移操作还是逻辑左移,但右移操作是采用逻辑右移还是算术右移就取决于机器了!( ...
- 关于C语言中不同类型数据进行计算 有符号和无符号数进行计算
float是8个有效位, 做个试验: 输出如下: 上面说明了什么: 1, 18/2.2 是除不尽的, 因为是define,所以没有给ratio变量赋值类型,但是从sizeof输出的结果是8,所以系统默 ...
- signed 与 unsigned 有符号和无符号数
unsigned int a = 0; unsigned int b = -1; // b 为 0xffffffff unsigned int c = a - 1; // c 为 0xffffffff
- C语言-无符号数与有符号数不为人知的秘密
一.无符号数与有符号数 1.计算机中的符号位 数据类型的最高位用于标识数据的符号 -最高位为1,表明这个数为负数 -最高位为0,表明这个数为正数 #include <stdio.h> in ...
- C语言中无符号数和有符号数之间的运算
C语言中无符号数和有符号数之间的运算 C语言中有符号数和无符号数进行运算(包括逻辑运算和算术运算)默认会将有符号数看成无符号数进行运算,其中算术运算默认返回无符号数,逻辑运算当然是返回0或1了. un ...
随机推荐
- 使用.net 自建短链接(短网址)
短连接大家都不陌生,例如新浪的 t.cn .京东的 3.cn .淘宝的 tb.cn 等等.都已经是家喻户晓的短连接域名.不知道有多少人像我一样,对短连接原理好奇而且尝试自建了呢? 今天发布这个文章的目 ...
- java 读取properties文件总结
一.java读取properties文件总结 在java项目中,操作properties文件是经常要做的,因为很多的配置信息都会写在properties文件中,这里主要是总结使用getResource ...
- java 基础语法 1
一.标识符 二.关键字 三.JAVA基础数据类型 3.1. java常量 3.2. java变量 从本质上来讲,变量其实是内存里面的一小块区域,一个程序在运行的时候,实际上这个程序是位于内存里面,然后 ...
- Maven在Windows中的配置以及IDE中的项目创建
Maven在Windows下的配置 1.Maven下载地址:http://maven.apache.org/download.cgi,下载红框里的版本即可. 2.解压到D盘: 3.修改配置文件sett ...
- P1034
问题 E: P1034 时间限制: 1 Sec 内存限制: 128 MB提交: 29 解决: 22[提交][状态][讨论版] 题目描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些 ...
- 微信小程序的跨平台图表库开发
写在前面 微信小程序出来已经有一段时间了,github上也有很多人开源了很多项目.但是由于微信平台的限制(底层Canvas能力调用为一系列JSBridge封装),图表的制作一直是个比较头疼的问题.当前 ...
- 【NOIP】OpenJudge - 15-02:财务管理
#include<stdio.h>//财务管理 int main() { ]={},sum=,ave=; ;i<=;i++) { scanf("%f",& ...
- php过滤textarea 中的换行符问题
之前我写的替换代码是这样的 $content = str_replace('\r\n', '', $_POST['content']); 为了确保window和Linux的换行符都能去掉,改成这样的: ...
- 在linux上安装rz、sz包
在SecureCRT这样的ssh登录软件里, 通过在Linux界面里输入rz/sz命令来上传/下载文件. 对于RHEL5, rz/sz默认没有安装所以需要手工安装.sz: 将选定的文件发送(send) ...
- CVPixelBuffer的创建 数据填充 以及数据读取
CVPixelBuffer的创建数据填充以及数据读取 CVPixelBuffer 在音视频编解码以及图像处理过程中应用广泛,有时需要读取内部数据,很少的时候需要自行创建并填充数据,下面简单叙述. 创建 ...