计算机中无符号整数和有符号整数

文章介绍了计算机中数的两种表示方式——有符号整数和无符号整数,强调了最高位作为符号位的区别以及无符号数不能表示负数的特点。此外,还讨论了补码的概念及其在存储负数和简化计算中的作用。同时,提到了不同类型之间的转换规则,特别是有符号数和无符号数之间的转换策略。

1.概念

计算机里的数是用二进制表示的,最左边的这一位一般用来表示这个数是正数还是负数,这样的话这个数就是有符号整数(signed integer)。如果最左边这一位不用来表示正负,而是和后面的连在一起表示整数,那么就不能区分这个数是正还是负,就只能是正数,这就是无符号整数(unsigned integer)。

计算机中的整数分为两类:不带符号位的整数(unsigned integer,也称为无符号整数),此类整数一定是正整数;带符号位的整数(signed integer),此类整数可以表示正整数,又可以表示负整数。

简明的说,无符号数就是其所有的位数都用来表示数值的大小,有符号数除最高位来表示数值的正负外(0表示正数;1表示负数),其余各位用来表示数值的大小。

举个例子说明一下:

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

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

2.存储范围

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

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

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

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

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

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

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

无符号整数常用于表示地址、索引等正整数,它们可以是8位、16位、32位、64位甚至更多。

8个二进制表示的正整数其取值范围是         0~255(2f1b4aa003571aee9013308d1edd2627.png -1)

16位二进制位表示的正整数其取值范围是    0~65535( a1c948759f8e500b5178b97787f87023.png -1)

32位二进制位表示的正整数其取值范围是    0~ 06344efd866c091b03aa869300577859.png-1

有符号和无符号的差别:

int是有符号的,unsigned是无符号的。

它们所占的字节数其实是一样的,但是有符号的需要安排一个位置来表达我这个数值的符号,因此说它能表示的绝对值就要比无符号的少一半。举个例子,我们有一个1个 [1]  字节的整数(虽然这种类型不存在),那么无符号的就是这样:00000000~11111111 这个就是无符号的范围。

一个字节是8位, 有符号的数,因为第一个位要用来表示符号,那么就只剩下7个位置可以用来表示数了0000000~1111111因为有符号,所以还可以表示范围:-1111 111 ~ +1111 111。

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

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

说一下各种码的概念吧。

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

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

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

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

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

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

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


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

从最低位开始至找到的第一个1均不变,符号位不变,这之间的各位“求反”(0变1;1变0)。
原码:1010 1001  补码:1101 0111.

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

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

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

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

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

5.转换大餐

有符号数的转换 

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

short

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

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

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

无符号数的转换

原类型目标类型转换方法
unsigned charchar最高为作符号位
unsigned charshort0扩展
unsigned charlong0扩展
unsigned charunsigned short0扩展
unsigned charunsigned long0扩展
unsigned charfloat转换到long;然后从long转换到float
unsigned chardouble转换到long;然后从long转换到double
unsigned charlong double转换到long;然后从long转换到long double
unsigned shortchar保留低位字节
unsigned shortshort最高为作符号位
unsigned shortlong0扩展
unsigned shortunsigned char保留低位字节
unsigned shortunsigned long0扩展
unsigned shortfloat转换到long;然后从long转换到float
unsigned shortdouble转换到long;然后从long转换到double
unsigned longlong double转换到long;然后从long转换到long double
unsigned longchar保留低位字节
unsigned longshort保留低位字节
unsigned longlong最高位作符号位
unsigned longunsigned char保留低位字节
unsigned longunsigned short保留低位字节
unsigned longfloat转换到long;然后从long转换到float
unsigned longdouble直接转换到double
unsigned longlong double转换到long;然后从long转换到long double

<think>嗯,用户这次想深入理解无符号整数有符号整数区别,而且提供了详细的引用资料。看来用户对计算机底层数据表示感兴趣,可能是程序员或计算机专业学生。 从引用材料看,用户已经掌握了基本概念:无符号整数只表示非负数,有符号整数可表示正负,两者在内存中都是补码存储但解释方式不同。不过用户似乎想更系统地了解差异点,需要帮ta梳理出结构化的对比。 核心区别其实在三个方面:表示范围、存储结构、运算特性。表示范围上,8位无符号是0-255,有符号是-128-127,这个差异会随着位数增加指数级扩大。存储结构的关键在于最高位——有符号整数的最高位是符号位(0正1负),而无符号整数所有位都是数值位。这导致运算时符号位会产生连锁反应,比如有符号数右移要补符号位(算术移位),而无符号数直接补0(逻辑移位)。 用户可能没意识到的是实际编程中的坑:比如C/C++里混用有符号无符号数时,编译器会隐式转换,可能导致负数被解释成超大正数。这点要重点强调,因为实际开发中经常引发bug。 性能方面虽然现代CPU差距不大,但在嵌入式领域仍有意义:无符号整数因无需处理符号,在除法、比较运算中通常更快。这个细节可以补充。 最后要提醒使用场景:数组索引、位操作首选无符号;涉及负数的业务逻辑必须用有符号。安全方面一定要强调溢出检查,无符号数溢出是定义良好的(回绕),但有符号数溢出是未定义行为,更危险。 用户给的引用[4][5]特别有用,其中1111 1111的例子很直观,可以拿来举例。不过要纠正引用[1]的小瑕疵——内存中其实能区分有无符号,只是同一串二进制解释不同而已。</think>### 无符号整数有符号整数的核心区别 #### 一、本质区别 1. **符号位与数值范围** - **有符号整数**:最高位为符号位(0表正数,1表负数),其余位表示数值。 - 例:8位有符号整数范围:$-128$ 到 $127$ - 二进制 `1111 1111` 表示 $-1$(补码形式)[^4] - **无符号整数**:所有位均为数值位,无符号位。 - 例:8位无符号整数范围:$0$ 到 $255$ - 二进制 `1111 1111` 表示 $255$[^4] 2. **存储空间与表示能力** - 相同位数下(如32位): | 类型 | 最小值 | 最大值 | |------------|---------------|----------------| | 有符号整数 | $-2^{31}$ | $2^{31}-1$ | | 无符号整数 | $0$ | $2^{32}-1$ | - **关键结论**:无符号整数正数范围更大(牺牲负数表示能力)[^2][^5]。 --- #### 二、技术实现差异 1. **补码机制** - 有符号整数采用**补码**存储: - 正数补码 = 原码 - 负数补码 = 原码取反 + 1 - 例:$-1$ 的8位补码 = `1111 1111`[^3][^4] - 无符号整数直接使用**原码**表示[^1][^5]。 2. **运算特性** - **溢出行为**: - 无符号整数:溢出时回绕(如 $255 + 1 = 0$) - 有符号整数:溢出是**未定义行为**(可能引发程序错误)[^5] - **移位操作**: - 无符号整数:右移补 $0$(逻辑移位) - 有符号整数:右移补符号位(算术移位) --- #### 三、应用场景对比 | **场景** | 推荐类型 | 原因 | |--------------------|------------------|----------------------------------------------------------------------| | 数组索引/循环计数 | 无符号整数 | 天然非负,避免负数错误;更大正数范围(如处理大型数组)[^1] | | 位操作/掩码运算 | 无符号整数 | 无符号位干扰,操作更直观(如IP地址处理)[^4] | | 金融计算/温度表示 | 有符号整数 | 需表示负值(如负债、零下温度) | | 性能敏感系统 | 无符号整数 | 某些CPU对无符号除法/比较有优化(嵌入式常见) | --- #### 四、编程注意事项 1. **隐式转换风险**(C/C++为例) ```c unsigned int a = 10; int b = -5; if (b < a) // b被隐式转换为无符号整数,-5 → 4294967291(32位系统) ``` **结果**:`-5 > 10` 成立![^1] **解决方案**:显式类型转换或避免混用。 2. **溢出防护** - 无符号整数:检查 `if (x + y < x)`(若成立说明溢出) - 有符号整数:使用编译器标志(如GCC的 `-ftrapv`)或手动检查边界。 --- #### 五、语言支持差异 | 语言 | 无符号语法 | 有符号语法 | 备注 | |---------|---------------------|------------|--------------------------| | C/C++ | `unsigned int x;` | `int x;` | 支持所有基础整数类型 | | Java | 不支持 | `int x;` | 仅通过`char`模拟无符号 | | C# | `uint x;` | `int x;` | 明确区分类型 | | Python | 无原生类型 | `int` | 自动处理大整数,无溢出 | > 关键参考:引用[1][3][4]强调**同一二进制在不同解释下的差异**;引用[2][5]说明**范围与存储结构的数学本质**。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值