Menu

C++ 数据类型:int、double、char、bool 等

实用的 C++ 基本数据类型指南:整数、浮点数、char 和 bool,以及类型大小、有符号与无符号、字面量和后缀、溢出,还有怎样选择合适的类型。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

为什么类型在 C++ 中很重要

当你用 int age = 30; 这样的显式类型声明一个值时,这个类型不只是一个标签:它告诉编译器要预留多少字节、怎样解释这些字节,以及哪些操作是合法的。类型选错了,你可能会悄无声息地丢失精度、发生溢出,或者触发未定义行为。

C++ 把内置类型分成几个家族:整数、浮点数、字符类型和布尔类型。我们逐个来看,然后再看那些容易让人栽跟头的规则。

基本类型

下面这个程序里,每种核心类型各有一个。注意字面量后缀(L、f、u)以及 char 用的单引号:

bool 默认打印为 1 或 0,而不是 true/false。char 用单引号:'A' 是一个字符,而 "A"(双引号)是字符串字面量,是完全不同的类型。这两个错误在刚开始学的时候极其常见。

大小并不固定

如果你学过 Java 这样的语言,这一点会让你最意外。C++ 标准只保证最小大小和相对顺序(short ≤ int ≤ long ≤ long long),实际大小取决于你的编译器和平台。务必用 sizeof 来确认:

在典型的 64 位 Linux 构建上,你会看到 int = 4,long = 8。但在 64 位 Windows 上,long 只有 4 个字节。正是这种可移植性上的差异,让你不应该写出假定 long 是 64 位的代码。

当你需要精确的宽度时,就使用 <cstdint> 中的定宽整数类型:

对于文件格式、网络协议,或者任何必须在不同机器上表现完全一致的东西,都使用 int32_t/int64_t。注意这里的强制转换 (int)a:把 8 位类型送进输出流时,它会被当作字符而不是数字打印,所以要先转换。

有符号与无符号

每种整数类型都有两种形式。signed 类型可以保存负数;unsigned 类型不行,它用负数范围换来了更大的正数上限。普通的 int 默认是有符号的。

从无符号的 0 中减去一个数,结果不会变成负数,而是绕回成一个巨大的正数。这个问题总是让人中招,尤其是 .size() 返回的 size_t(一种无符号类型):

vector<int> v = {1, 2, 3};
// DANGER: v.size() is unsigned. If v is empty, v.size() - 1 wraps
// to a gigantic number and the loop runs nearly forever.
for (size_t i = 0; i <= v.size() - 1; i++) { /* ... */ }

优先写 i < v.size()(永远不要写 <= size() - 1),或者干脆用基于范围的 for 循环绕开整个问题。

整数溢出是未定义行为

无符号数的绕回是有明确定义的,而有符号整数溢出在 C++ 中却是未定义行为。编译器可以做任何事:返回垃圾值、把检查优化掉,或者直接崩溃:

解决办法和任何语言中的溢出陷阱一样:在更宽的类型中做运算。在 + 之前先把其中一个操作数转换成 long long,让加法以 64 位进行。事后再转换结果就太晚了,溢出已经发生了。

选择合适的类型

对大多数代码来说,默认选择就够了:整数用 int,小数用 double。只有在确实有理由时才换用别的类型。

类型常见大小适用场景
int32 位整数的默认选择
long long64 位超过约 20 亿的值:时间戳、大计数器
double64 位小数的默认选择,精度好
float32 位内存紧张、可以牺牲精度的数组
bool1 字节真/假标志
int32_t / int64_t精确跨平台格式、协议、位操作

还有几个坑要记住。float 只有大约 7 位有效十进制数字,所以 0.1f + 0.2f 并不精确等于 0.3。除非你真的需要节省内存,否则优先用 double。另外,char 是有符号还是无符号取决于平台,所以如果你要对原始字节做运算,就明确写出 signed char 或 unsigned char。

下一步:auto 关键字

每次都把类型写出来很繁琐,而且有时类型很长,或者很难写出名字。C++ 让编译器通过 auto 关键字替你推导类型:auto x = 42; 让 x 成为 int,auto it = v.begin(); 让你不必敲出冗长的迭代器类型。下一页讲解什么时候 auto 能让代码更清晰,什么时候它又隐藏了太多信息。

常见问题

C++ 的基本数据类型有哪些?

基本类型包括整数(short、int、long、long long)、浮点数(float、double、long double)、字符类型 char 和布尔类型 bool。每种整数类型还可以是 signed 或 unsigned。其他一切,比如 std::string、数组和你自己写的类,都建立在这些类型之上。

C++ 中 int 和 long 有什么区别?

两者都保存整数,但 long 保证至少和 int 一样宽(在 64 位平台上通常是 64 位,但在 Windows 上只有 32 位)。标准只规定了最小大小,所以如果需要确定的宽度,就使用 <cstdint> 中的定宽类型,比如 int32_t 和 int64_t。

C++ 中的 int 有多大?

标准只保证 int 至少有 16 位,但在几乎所有现代桌面电脑和服务器上它都是 32 位。由于大小取决于平台,永远不要想当然:打印 sizeof(int) 来确认,或者在需要精确宽度时使用 int32_t 这样的 <cstdint> 类型。

Coddy 编程语言插图

和 Coddy 一起学编程

开始