unsigned类型与signed类型的区别介绍
文章目录
- 1. char 类型的signed 和 unsigned
- 1.1 主要区别
- 1.2 **存储方式**
- 1.3 **符号位解释**
- 2. int 类型(unsigned 与 signed)
- **2.1 存储方式**
- **2.2 取值范围**
- **2.3 运算行为**
- **(1) 负数运算**
- **(2) 比较运算**
- **2.4 何时使用 `int` 和 `unsigned int`**
- **(1) 适合使用 `int` 的情况**
- **(2) 适合使用 `unsigned int` 的情况**
- **2.5 结论**
- 3. char int a= -6; 存储原理
- `char a = -6;` 的底层存储
- 1. **正数的存储方式**
- 2. **负数的存储方式(补码)**
- 3. **存储情况**
- **存储示例**
- **验证 C 代码**
- **总结**
**使用时候千万要注意!特别是char类型(8bit), short类型(16bit) **
signed 类型的 char,由于 signed类型最高bit位 例如char(8bit)最高bit位 bit7被拿去做正负符号位了,所以char类型存储值只有7bit,最大值也就是127,不要给其赋值 超过127了,否则系统会崩溃的!
1. char 类型的signed 和 unsigned
1.1 主要区别
类型 | 取值范围 | 是否可能存储负数 | 编译器行为 |
---|---|---|---|
unsigned char | 0 ~ 255 | 不能 | 计算时按无符号处理 |
char (可能 signed ) | -128 ~ 127 | 可能 | 计算时按补码规则处理 |
1.2 存储方式
无论 char
还是 unsigned char
,在大多数平台(如 x86 和 ARM)上,它们都占 1 个字节(8 bit),存储的二进制数据是相同的。例如:
unsigned char a = 6; // 0000 0110(二进制)
char a = 6; // 0000 0110(二进制)
从存储角度看,它们的二进制表示完全一致。
1.3 符号位解释
unsigned char
(无符号):- 取值范围:0 ~ 255
- 直接解释为无符号整数。
char
(有符号):- 取值范围:-128 ~ 127
- 最高位(bit7)通常被解释为 符号位(0 表示正,1 表示负)。
例如:
unsigned char a = 200; // 存储二进制: 1100 1000 (200)
char b = 200; // 存储二进制: 1100 1000
在存储上是一样的,但 char b
可能会被解释为 -56(假设使用补码存储方式)。
unsigned char a = 200;
char b = 200;
printf("%d\n", a); // 输出 200
printf("%d\n", b); // 可能输出 -56(补码表示)
2. int 类型(unsigned 与 signed)
2.1 存储方式
无论 int
还是 unsigned int
,在大多数主流平台(如 x86、ARM) 上,它们通常占 4 个字节(32 位),存储的二进制数据是相同的。例如:
int a = 997; // 00000000 00000000 00000011 11100101(二进制表示)
unsigned int b = 997;// 00000000 00000000 00000011 11100101(二进制表示)
在存储层面,它们的二进制数据是一样的。
2.2 取值范围
-
int
(有符号,signed int
的简写)- 取值范围(32 位系统):
-2,147,483,648
~2,147,483,647
- 最高位(bit31)为 符号位(0 表示正,1 表示负)。
- 取值范围(32 位系统):
-
unsigned int
(无符号)- 取值范围(32 位系统):
0
~4,294,967,295
- 所有 32 位都用于存储数值,没有符号位。
- 取值范围(32 位系统):
对于 997
这个值来说:
- 无论
int
还是unsigned int
,它们的存储数据相同,因为997
在两者的表示范围内。 - 但如果是
-1
,则:int a = -1; // 存储二进制: 11111111 11111111 11111111 11111111 (补码表示) unsigned int b = -1;// 存储二进制: 11111111 11111111 11111111 11111111 (相同的位模式)
int a = -1;
会被解释为-1
,而unsigned int b = -1;
会被解释为4294967295
(无符号最大值)。
2.3 运算行为
(1) 负数运算
int
支持负数,例如:int a = -10; printf("%d\n", a); // 输出 -10
unsigned int
不能存负数,如果赋值-10
,它会发生溢出,实际存的值是:unsigned int b = -10; printf("%u\n", b); // 4294967286(因为 -10 以补码存储,解释成无符号数)
(2) 比较运算
int x = -1;
unsigned int y = 1;
if (x > y) {
printf("x is greater\n");
} else {
printf("y is greater\n");
}
你可能期望 x > y
不成立,但 x
实际上存储的是 0xFFFFFFFF
(即 4294967295
),所以 x > y
实际上是成立的!
2.4 何时使用 int
和 unsigned int
(1) 适合使用 int
的情况
- 需要存储 负数(如温度、位移、差值计算)。
- 需要使用 标准算术运算,避免
unsigned
计算带来的异常结果。
(2) 适合使用 unsigned int
的情况
- 只需要存储 非负整数,例如数组索引、内存地址、文件大小等。
- 需要存储 更大的正整数(例如
unsigned int
最高可到4,294,967,295
,比int
的2,147,483,647
大一倍)。 - 进行位操作时,
unsigned
避免了符号位的干扰。
2.5 结论
类型 | 存储大小(通常) | 取值范围(32 位) | 最高位作用 | 负数支持 |
---|---|---|---|---|
int (有符号) | 4 字节(32 位) | -2,147,483,648 ~ 2,147,483,647 | 符号位 | 支持 |
unsigned int (无符号) | 4 字节(32 位) | 0 ~ 4,294,967,295 | 仅数值 | 不支持 |
- 在底层存储上,相同值(997)的二进制存储是一样的。
- 区别主要在于数值解释、负数处理、运算规则、比较方式等方面。
3. char int a= -6; 存储原理
char a = -6;
的底层存储
char
在 存储负数时 采用 补码(Two’s Complement)表示法。假设 char
是 有符号(signed char
),存储范围为 -128 到 127。
1. 正数的存储方式
在 8 位有符号整数(signed char
)中:
- 正数 直接用 二进制原码 存储,例如:
char a = 6;
- 二进制(原码):
00000110
(十进制 6)
- 二进制(原码):
2. 负数的存储方式(补码)
负数 以补码存储,求 -6 的补码方法:
- 先求 6 的二进制(8 位):
00000110 (6 的原码)
- 取反(按位取反):
11111001 (取反)
- 加 1(得到补码):
11111010 (-6 的补码)
3. 存储情况
如果 char a = -6;
,在 内存中存储的是 11111010
(十六进制 0xFA
)。
存储示例
假设 char a = -6;
在内存地址 0x1000
处存储:
地址 值(十六进制) 值(二进制)
0x1000 0xFA 11111010
验证 C 代码
可以用 C 代码验证:
#include <stdio.h>
int main() {
char a = -6;
printf("a = %d\n", a);
printf("a in hex: 0x%X\n", (unsigned char)a); // 强制转无符号,显示存储值
return 0;
}
输出:
a = -6
a in hex: 0xFA
可以看到,-6
以 0xFA
(补码) 形式存储。
总结
- 负数在计算机中采用补码存储。
-6
的 补码 是11111010
(十六进制0xFA
)。- 计算机在读取
char
时,会按照补码规则解析,所以0xFA
解释为-6
。
⚠️ 注意
unsigned char
不会存负数,如果unsigned char a = -6;
,会导致值变成250
(0xFA 解释为无符号)!