章节目录

有符号整数

本节阅读量:

整数是一种整数类型,可以表示正整数和负整数,包括0(例如,-2,-1,0,1,2)。C++有4种主要的基本整数类型可供使用:

类型 最小大小(字节)
short int 2
int 2 现代机器上通常是4个字节
long int 4
long long int 8

各种整数类型之间的关键区别在于它们具有不同的大小——较大的整数可以容纳较大的数字。


有符号整数

在日常生活中写负数时,我们使用负号。例如,-3表示“负3”。我们通常也会将+3识别为“正3”(尽管通常的约定规定我们通常省略加号前缀)。

正、负或零的属性称为数字的符号。

默认情况下,C++中的整数是有符号的,这意味着数字的符号存储为数字的一部分。因此,有符号整数可以同时包含正数和负数(和0)。

在本课中,我们将重点讨论有符号整数。在下一课中,我们将讨论无符号整数(它只能容纳非负数)。


定义有符号整数

下面是定义四种类型的有符号整数的首选方法:

1
2
3
4
short s;      // 优先使用 "short" 而不是 "short int"
int i;
long l;       // 优先使用 "long" 而不是 "long int"
long long ll; // 优先使用 "long long" 而不是 "long long int"

尽管short int、long int或long long int可以正常使用,但我们更喜欢这些类型的短名称(不使用int后缀)。添加int后缀还会使类型更难与int类型的变量区分。如果无意中遗漏了short修饰符或long修饰符,这可能会导致错误。

整数类型也可以采用可选的带符号关键字,根据约定,该关键字通常放在类型名称之前:

1
2
3
4
signed short ss;
signed int si;
signed long sl;
signed long long sll;

然而,不应该使用该关键字,因为它是冗余的,因为默认情况下整数是有符号的。


有符号整数范围

正如您在上一节中所了解的,具有n位的变量可以保存2的n次方个可能的值。但具体的值范围是什么?整数变量的范围由两个因素决定:它的大小(以位为单位),以及它是否有符号。

根据定义,8位有符号整数的范围是-128到127。这意味着有符号整数可以安全地存储-128到127(含)之间的任何整数值。

下面是一个包含不同大小的有符号整数范围的表:

类型大小 取值范围
8位 -128 to 127
16位 -32,768 to 32,767
32位 -2,147,483,648 to 2,147,483,647
64位 -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

用数学公式来表示,n位有符号变量的范围为-(2^n-1)到2^(n-1)-1。


溢出(Overflow)

如果尝试将值140赋给8位有符号整数,会发生什么情况?此数字超出8位有符号整数可以容纳的范围。数字140需要9位来表示(8个量值位和1个符号位),但在8位有符号整数中,我们只有8位(7个值比特和1个符号比特)可用。

C++20标准做出了这样的总括声明:“如果在表达式求值期间,结果没有在数学上定义,或者不在其类型的可表示值范围内,则行为是未定义的”。通俗地说,这称为溢出。

因此,将值140分配给8位有符号整数将导致未定义的行为。

如果算术运算(如加法或乘法)试图在可以表示的范围之外创建值,则这称为整数溢出(或算术溢出)。对于有符号整数,整数溢出将导致未定义的行为。

通常,溢出会导致信息丢失,这几乎是不可取的。如果怀疑对象可能需要存储超出其范围的值,请使用范围更大的类型!


整数除法

对两个整数进行除法时,当结果为整数时,C++的运行结果与预期一致:

1
2
3
4
5
6
7
#include <iostream>

int main()
{
    std::cout << 20 / 4 << '\n';
    return 0;
}

这会产生预期的结果:

1
5

但让我们看看整数除法产生分数结果时会发生什么:

1
2
3
4
5
6
7
#include <iostream>

int main()
{
    std::cout << 8 / 5 << '\n';
    return 0;
}

这可能会产生意外的结果:

1
1

对两个整数进行除法(称为整数除法)时,C++始终生成整数结果。由于整数不能保存分数,因此任何分数部分都会被丢弃(而不是取整!)。

仔细看一下上面的例子,8/5产生值1.6。删除小数部分(0.6),保留1的结果。或者,我们可以说8/5等于1余数3。余数被丢弃,留下1。

类似地,-8/5产生值-1。

如果需要分数结果,我们在后续课程中展示如何操作。


4.2 对象大小和sizeof运算符

上一节

4.4 无符号整数,以及为什么要避免使用它们

下一节