在 C++ 中,整型数据可以分为有符号数(Signed)和无符号数(Unsigned),这两种类型主要用于表示整数值,但它们在表示范围和用途方面有所不同。默认情况下,整数类型如 int、short、long 都是有符号数,通过在这些类型前加上 unsigned
关键字可以定义无符号数(例如:unsigned long
)。字符型 char
可以是有符号的或无符号的,具体取决于编译器的默认设置。
有符号数 (Signed)
有符号整数可以表示正数、负数以及零。C++ 中的有符号整型包括:
-
short
或signed short
-
int
或signed int
-
long
或signed long
-
long long
或signed long long
有符号整型的表示范围是对称的,以 0 为中心,向正负两方向延伸。例如,如果一个有符号整型用 8 位(1 字节)表示,则其范围是从-128 到 127。这是因为其中一个位用于表示符号(通常是最高位),剩余的位表示大小。这一部分上一节中已经详细介绍了,有兴趣的朋友可以去看看。
无符号数 (Unsigned)
无符号整数仅用于表示非负数(包括零)。C++ 中的无符号整型包括:
unsigned short
unsigned int
unsigned long
unsigned long long
无符号整型的表示范围从 0 开始,向正方向延伸。继续上面的例子,如果一个无符号整型用 8 位表示,则其范围是从 0 到 255。所有的位都用于表示大小,没有位被用于表示符号。
表示范围
无符号数的表示范围是有符号数的两倍,但它不能表示负数。
名称 | 大小(字节) | 取值范围 | 说明 |
| 1 | 0 到 255 | 通常用于存储小的非负整数或字符。 |
| 2 | 0 到 65,535 | 适用于存储中等大小的非负整数。 |
| 4 | 0 到 4,294,967,295 | 常用于存储大的非负整数。一般来说,这是最常用的无符号整数类型。 |
| 4 或 8 | 0 到 4,294,967,295 或更大 | 用于存储大的非负整数,其具体大小依赖于编译器和平台。 |
| 8 | 0 到 18,446,744,073,709,551,615 | 用于存储非常大的非负整数。 |
有符号数与无符号数的区别
区别
有符号数是最高位为符号位,0 代表正数,1 代表负数。
#include <iostream> // 引入输入输出流库
using namespace std; // 使用标准命名空间,避免每次调用标准库函数时都要加std::
int main() // 主函数入口
{
signed int a = -1089474374; // 定义一个有符号整型变量a,并赋值为-1089474374
cout << std::hex << a << endl; // 将cout的输出格式设置为十六进制,并输出变量a的值,然后输出一个换行符
si
// b f 0 f f 0 b a
// 1011 1111 0000 1111 1111 0000 1011 1010
return 0; // 返回0,正常结束程序
}
这段代码的作用是定义一个有符号整数 a
,并将其初始化为 -1089474374
。然后,使用 cout
以十六进制的形式输出这个整数的值,最后以换行符结束输出。
signed int a = -1089474374;
:这里定义了一个signed int
(有符号整型)变量a
,并给它赋了一个负值-1089474374
。cout << std::hex << a << endl;
:
-
std::hex
:这是一个 I/O 操作符,用来告诉cout
后续的整数输出应该以十六进制的形式表示。 -
a
:输出变量a
的值,由于之前指定了十六进制格式,所以a
的值将以十六进制形式显示。 -
endl
:这是一个操作符,用来在输出流中插入一个换行符,并刷新输出缓冲区,使得输出立即出现在目标设备上(如屏幕)。
b f 0 f f 0 b a
是a
的十六进制表示,对应的二进制形式是1011 1111 0000 1111 1111 0000 1011 1010
。十六进制的每一位对应二进制的四位,从左到右依次是:b
(1011)、f
(1111)、0
(0000)、f
(1111)、f
(1111)、0
(0000)、b
(1011)、a
(1010)。可以看到它的最高位为 1,表示它为负数。
无符号数最高位不是符号位,而就是数的一部分,无符号数不可能是负数。
十进制数 3236958022 的二进制表示方式为:1011 1111 0000 1111 1111 0000 1011 1010
如果将其当作无符号数来看待,那么它的原码为: 1100 0000 1111 0000 0000 1111 0100 0110,
十六进制表示为:c 0 f 0 0 f 4 6
#include <iostream> // 引入标准输入输出流库,用于输入输出操作
using namespace std; // 使用标准命名空间std,避免每次调用标准库函数时都要加std::
int main() // 主函数入口,程序从这里开始执行
{
unsigned int a = 3236958022; // 定义一个无符号整型变量a,并赋值为3236958022
cout << std::hex << a << endl; // 将cout的输出格式设置为十六进制,并输出变量a的值,然后输出一个换行符
return 0; // 主函数返回0,表示程序正常结束
}
unsigned int a = 3236958022;
:这里定义了一个unsigned int
(无符号整型)变量a
,并将其初始化为3236958022
。cout << std::hex << a << endl;
:跟上个例子一样,这一行代码使用cout
来输出变量a
的值,但在输出之前,使用std::hex
来指定输出格式为十六进制。endl
是用来在输出的末尾添加一个换行符,并且刷新输出缓冲区,确保输出立即显示。
-
std::hex
:这个操作符改变了cout
的状态,使得随后的整型输出以十六进制形式展示。 -
a
:输出变量a
的值。由于cout
已经被设置为十六进制输出模式,所以a
的值会以十六进制形式显示。 -
endl
:在输出流中插入一个换行符,并刷新输出缓冲区,使得输出立即显示在目标设备上(例如屏幕)。
从输出结果可以看出,与在开头部分分析的一样,输出的十六进制为 c0f00f46,这表示无符号数最高位不是符号位,而就是数的一部分。
有符号数和无符号数的使用建议
- 当明确知道数值不会是负数时,建议使用无符号数。
- 当需要表示的数可能为负值,应使用有符号整数。
- 如果预期算术运算可能产生负数结果,使用有符号整数可以避免无符号数溢出的问题。
- 无符号数可以表示比相同大小的有符号数更大的正数值。