基础类型
(类型系统概览见类型,以及参阅 C++ 库提供的类型相关的工具列表)
void 类型
- void - 值为空集的类型。它是无法变为完整的不完整类型(从而不允许存在 void 类型的对象)。不存在含有 void 的数组以及到 void 的引用。然而 指向 void 的指针和返回 void 类型的函数是允许存在的(其他语言中的过程)。
std::nullptr_t (C++11 起)
在标头 <cstddef> 定义
|
||
typedef decltype(nullptr) nullptr_t; |
(C++11 起) | |
std::nullptr_t 是空指针字面量 nullptr
的类型。它是独立类型,既不是指针类型,也不是成员指针类型。
数据模型
每个实现关于基础类型大小所做的选择被统称为数据模型。有四个数据模型广为接受:
32 位系统:
- LP32 或 2/4/4(int 是 16 位,long 和指针是 32 位)
- Win16 API
- ILP32 或 4/4/4(int、long 和指针是 32 位)
- Win32 API
- Unix 和类 Unix 系统(Linux、macOS)
64 位系统:
- LLP64 或 4/4/8(int 和 long 是 32 位,指针是 64 位)
- Win32 API (也叫 Windows API) 编译目标为 64-bit ARM (AArch64) 或者 x64 (x86-64)
- LP64 或 4/8/8(int 是 32 位,long 和指针是 64 位)
- Unix 和类 Unix 系统(Linux、macOS)
其他数据模型很罕见。例如,ILP64(8/8/8:int、long 和指针是 64 位)只会在某些早期 64 位 Unix 系统出现(例如 UNICOS on Cray)。
整数类型
标准整数类型
- int - 基本整数类型。如果使用了下列任何修饰符就可以省略关键词 int。如果没有长度修饰符,那么它保证拥有至少 16 位宽度。然而在 32/64 位系统上,几乎专门保证它拥有至少 32 位宽度(见后述)。
修饰符
修饰整数类型。能以任何顺序混合使用。类型名中每组只能有一个。
- 符号性
- signed - 目标类型将拥有有符号表示(默认符号性)
- unsigned - 目标类型将拥有无符号表示
- 大小
- short - 目标类型将为空间优化,且将有至少 16 位的宽度。
- long - 目标类型将有至少 32 位的宽度。
|
(C++11 起) |
注意:与所有类型说明符相同,容许采用任何顺序:unsigned long long int 与 long int unsigned long 指名同一类型。
性质
下表总结了所有可用的整数类型及它们在各种常用数据模型中的性质:
类型说明符 | 等价类型 | 按数据模型的位宽 | ||||
---|---|---|---|---|---|---|
C++ 标准 | LP32 | ILP32 | LLP64 | LP64 | ||
short
|
short int | 至少 16 | 16 | 16 | 16 | 16 |
short int
| ||||||
signed short
| ||||||
signed short int
| ||||||
unsigned short
|
unsigned short int | |||||
unsigned short int
| ||||||
int
|
int | 至少 16 | 16 | 32 | 32 | 32 |
signed
| ||||||
signed int
| ||||||
unsigned
|
unsigned int | |||||
unsigned int
| ||||||
long
|
long int | 至少 32 | 32 | 32 | 32 | 64 |
long int
| ||||||
signed long
| ||||||
signed long int
| ||||||
unsigned long
|
unsigned long int | |||||
unsigned long int
| ||||||
long long
|
long long int (C++11) |
至少 64 | 64 | 64 | 64 | 64 |
long long int
| ||||||
signed long long
| ||||||
signed long long int
| ||||||
unsigned long long
|
unsigned long long int (C++11) | |||||
unsigned long long int
|
注意:整数算术对有符号和无符号整数类型的定义是不同的。见算术运算符,特别是整数溢出。
std::size_t 是 sizeof
运算符还有 sizeof...
运算符及 alignof
运算符 (C++11 起)的结果的无符号整数类型。
扩展整数类型 (C++11 起)
扩展整数类型由实现定义。注意定宽整数类型典型情况下是标准整数类型的别名。
布尔类型
字符类型
- signed char - 有符号字符表示的类型。
- unsigned char - 无符号字符表示的类型。也会用来审查对象表示(无修饰内存)。
- char - 能在目标系统上最有效地处理的字符表示的类型(拥有与 signed char 或 unsigned char 之一相同的表示和对齐,但始终是独立的类型)。多字节字符串用此类型表示编码单元。对于每个范围
[0, 255]
中的 unsigned char 类型值,将该值转换成 char 再转换回 unsigned char 产生原值。 (C++11 起) char 的符号性取决于编译器和目标平台:ARM 和 PowerPC 的默认设置通常没有符号,而 x86 与 x64 的默认设置通常有符号。 - wchar_t - 宽字符表示的类型(见宽字符串)。它与上述整数类型之一具有相同的大小、符号性和对齐,但它是独立的类型。实践中,它在 Linux 与许多其他非 Windows 系统上为 32 位并保有 UTF-32,但在 Windows 上为 16 位并保有 UTF-16 编码单元。标准曾要求 wchar_t 足够大以保有任何受支持的字符码位。然而该要求无法在 Windows 上满足,从而它被视为缺陷并被移除。
|
(C++11 起) |
|
(C++20 起) |
除了最小位数,C++ 标准还保证
- 1 == sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long) ≤ sizeof(long long)。
注意:这允许一种极端情况,其中字节有 64 位大小,所有类型(包括 char)都有 64 位宽,而 sizeof 对每个类型均返回 1。
浮点类型
标准浮点类型
下列三种类型和它们的 cv 限定版本统称为标准浮点类型。
- float - 单精度浮点类型。如果支持就会匹配 IEEE-754 binary32 格式。
- double - 双精度浮点类型。如果支持就会匹配 IEEE-754 binary64 格式。
- long double - 扩展精度浮点类型。如果支持就会匹配 IEEE-754 binary128 格式,否则如果支持就会匹配 IEEE-754 binary64 扩展格式,否则匹配某种精度优于 binary64 而值域至少和 binary64 一样好的非 IEEE-754 扩展浮点格式,否则匹配 IEEE-754 binary64 格式。
- 一些 HP-UX、SPARC、MIPS、ARM64 和 z/OS 实现使用 binary128 格式。
- 最知名的 IEEE-754 binary64 扩展格式是 80 位 x87 扩展精度格式。许多 x86 和 x86-64 实现使用它(一个典型的例外是 MSVC,它将 long double 实现为与 double 相同的格式,即 binary 64)。
扩展浮点类型 (C++23 起)
扩展浮点类型由实现定义。可能会包含定宽浮点类型。
性质
浮点类型可以支持一些特殊值:
- 无穷(正和负),见 INFINITY
- 负零,-0.0。它与正零比较相等,但在某些算术运算中有意义,例如 1.0 / 0.0 == INFINITY,但 1.0 / -0.0 == -INFINITY),而且对某些数学函数有意义,例如 sqrt(std::complex)
- 非数(NaN),它与任何值(包括自身)比较都不相等。多个位模式都表示 NaN,见 std::nan、NAN。注意 C++ 并会不对发信 NaN 进行特殊对待,它会把所有 NaN 都当做静默 NaN,但提供了 std::numeric_limits::has_signaling_NaN 用以检测它们的支持情况。
实浮点数可以用于算术运算符 + - / * 和各种来自 <cmath> 的数学函数。内建运算符和库函数都可能会引发浮点异常,并按 math errhandling 中的描述设置 errno。
浮点表达式可以拥有大于它的类型所指定的值域和精度,见 FLT_EVAL_METHOD。浮点表达式也可以收缩,即在计算时将所有中间值视为拥有无限范围和精度,见 #pragma STDC FP_CONTRACT。标准 C++ 不限制浮点操作的准确度。
浮点数上的某些运算受浮点环境的状态影响,并可以对它进行修改(最值得注意的是舍入方向)。
在实浮点类型和整数类型间定义了隐式转换。
浮点类型的其他细节、界限和性质见浮点类型的界限和 std::numeric_limits。
取值范围
下表提供常用数值表示的界限的参考。
C++20 之前,C++ 标准曾允许任意的有符号整数表示,而 N 位有符号整数的最小保证范围从 -(2N-1
-1) 到 +2N-1
-1(例如有符号 8 位类型是 -127 到 127),这与反码或原码的界限对应。
然而,所有 C++ 编译器均使用补码表示,而从 C++20 起,这是标准所允许的唯一表示,所保证的范围从 -2N-1
到 +2N-1
-1(例如有符号 8 位类型是 -128 到 127)。
C++11 起(经由 CWG 问题 1759的解决方案)char 不能再由 8 位反码与原码表示,因为用于 UTF-8 字符串字面量的值为 0x80 的 UTF-8 编码单元必须能在 char 类型对象中存储。
类型 | 位数 | 格式 | 取值范围 | |
---|---|---|---|---|
近似 | 精确 | |||
字符 | 8 | 有符号 | -128 到 127 | |
无符号 | 0 到 255 | |||
16 | UTF-16 | 0 到 65535 | ||
32 | UTF-32 | 0 到 1114111 (0x10ffff) | ||
整数 | 16 | 有符号 | ± 3.27 · 104 | -32768 到 32767 |
无符号 | 0 到 6.55 · 104 | 0 到 65535 | ||
32 | 有符号 | ± 2.14 · 109 | -2,147,483,648 到 2,147,483,647 | |
无符号 | 0 到 4.29 · 109 | 0 到 4,294,967,295 | ||
64 | 有符号 | ± 9.22 · 1018 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | |
无符号 | 0 到 1.84 · 1019 | 0 到 18,446,744,073,709,551,615 | ||
二进制浮点 | 32 | IEEE-754 |
|
|
64 | IEEE-754 |
|
| |
80[注 1] | x86 |
|
| |
128 | IEEE-754 |
|
|
- ↑ 在 32/64 位平台上对象表示通常占用 96/128 位。
注意:这些类型能够表示的值的实际界限(与保证的最小界限相对)可以通过 C 数值界限接口和 std::numeric_limits 获知。
注解
功能特性测试宏 | 值 | 标准 | 注释 |
---|---|---|---|
__cpp_unicode_characters |
200704L | (C++11) | 新字符类型 (char16_t 和 char32_t) |
__cpp_char8_t |
201811L | (C++20) | char8_t |
202207L | (C++23) | char8_t 兼容性和移植性修复 (允许从 UTF-8 string literals 聚合初始化 (unsigned) char 数组)
|
关键词
void, bool, true, false, char, wchar_t, char8_t, (C++20 起) char16_t, char32_t, (C++11 起) int, short, long, signed, unsigned, float, double
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
CWG 238 | C++98 | 未指明浮点实现会受哪些约束 | 指明不受约束 |
CWG 1759 | C++11 | 不保证 char 能表示 UTF-8 代码单元 0x80 | 已保证 |
P2460R2 | C++98 | wchar_t 需要能够以不同代码表示所有支持的本地环境中最大的扩展字符集中的每个成员 | 不再需要 |