C++ 数据类型

在编写程序时,我们会遇到各种各样的数据:比如年龄 20 是整数,身高 1.75 是小数,等级 'A' 是单个字符,而 “是否已登录” 则只有真和假两种状态。

在 C++ 中,所谓的 “数据类型”,说白了就是变量的 “值” 的类型。我们在定义变量时写出数据类型,是为了告诉编译器:这个数据属于哪一类,应该分配多大的内存空间、按照什么规则去保存和运算。

C++ 提供了丰富的数据类型,刚入门时小伙伴们完全没必要一口气全背下来。现阶段我们先重点掌握以下 4 种最常用的基础数据类型就可以了:

  • 整数类型(int):用来表示没有小数部分的整数。
  • 浮点类型(double):用来表示带有小数部分的数字。
  • 字符类型(char):用来表示单个英文字符或符号。
  • 布尔类型(bool):用来表示 “真” 或 “假” 两种状态。

C++ 基础数据类型

在日常编写基础程序时,int、double、char 和 bool 是出场率最高的 4 种基础数据类型,下面我们结合具体示例来看看它们的用法。

1. 整数类型(int)

在 C++ 中,整数类型也叫做 “整型”。其中 int 是英文单词 “integer(整数)” 的缩写,专门用来保存没有小数部分的数,包括正整数、0 和负整数。像平时常见的商品数量、考试分数、零下温度等整数数据,我们通常都优先使用 int。

示例 1:使用 int 类型

#include <iostream>

int main() {
    int count = 12;
    int temperature = -5;
    std::cout << count << " " << temperature;
    return 0;
}

运行结果如下。

12 -5

分析:

在这个例子中,我们使用 int 定义了两个整型变量:count 保存正整数 12,temperature 保存负整数 -5。像这样直接写在代码里的 12、-5 等具体数值,在编程中也叫做 “字面量”。

需要注意的是,int 能表示的整数范围并不是无限大的。在主流 64 位电脑上,int 通常能表示约 -21 亿到 +21 亿之间的整数,应付日常普通整数已经完全够用了。至于超出范围会发生什么,我们会在下面第二小节具体演示。

2. 浮点类型(double)

在 C++ 中,浮点数类型也叫做 “浮点型”,指的是带有小数部分的数字,比如身高 1.75、商品单价 19.8、圆周率 3.1415926 等。日常开发中最常用的小数类型是双精度浮点型(double)。

示例 2:使用 double 类型

#include <iostream>

int main() {
    double height = 1.75;
    double pi = 3.1415926;
    std::cout << height << " " << pi;
    return 0;
}

运行结果如下。

1.75 3.14159

分析:

这里我们定义了 height 和 pi 两个 double 变量来保存小数。细心的小伙伴可能会好奇:pi 赋的值明明是 3.1415926,为什么屏幕上只打印出了 3.14159 呢?

其实 pi 在内存中依然完整保存着 3.1415926,只是 std::cout 默认最多显示 6 位有效数字,并且像 3.0 这样小数部分为 0 的数会默认显示成 3。如果需要指定小数点后保留几位,可以配合输出格式化工具来实现。

另外要注意,千万不要把带有小数的数字误赋给 int 整型变量。由于 int 无法保存小数部分,小数点后面的 .75 会直接丢失,变量里最终只剩下整数 1:

int height = 1.75;    // 小数部分丢失,结果变成 1

在 C++ 的浮点类型家族里,除了 double 之外,还有单精度浮点型(float)和扩展精度浮点型(long double):

float speed = 3.5f;               // 单精度,末尾常加 f
double height = 1.75;             // 双精度(推荐)
long double distance = 100.0L;    // 扩展精度,末尾常加 L

代码里直接写出的小数字面量默认就是 double 类型,末尾加上后缀 f 或 L 则分别表示 float 或 long double。由于 double 约有 15 位有效数字精度,远高于 float 的 6~7 位,平时表示小数统一优先使用 double 即可。

注意 浮点数在计算机底层采用二进制近似保存,存在微小的精度误差。比如计算 0.1 + 0.2 时,底层结果可能是 0.30000000000000004,因此平时不要直接判断两个浮点数是否完全相等。

3. 字符类型(char)

在 C++ 中,char 是英文单词 “character(字符)” 的缩写,用来保存单个字符,比如一个英文字母 'A'、一个数字字符 '7' 或一个英文符号 '#'。书写字符字面量时,必须使用一对英文单引号括起来。

示例 3:使用 char 类型

#include <iostream>

int main() {
    char grade = 'A';
    char symbol = '#';
    std::cout << grade << " " << symbol;
    return 0;
}

运行结果如下。

A #

分析:

'A' 和 '#' 都是单个字符,并且用英文单引号括了起来。可能有些小伙伴会问:“数字字符 '7' 和整数 7 有什么区别呢?” 其实,不加引号的 7 是整数,可以直接参与加减乘除。而加了单引号的 '7' 只是代表字符符号,不能直接当成整数 7 去算数学题。

在使用 char 类型时,我们需要避开下面两种常见错误:

// 正确方式
char grade = 'A';

// 错误方式
char grade = "A";     // 不能使用双引号
char grade = 'AB';    // 只能保存单个字符

在 C++ 中,单引号和双引号的含义完全不同:'A' 表示单个字符,而 "A" 表示字符串,两者不能混用。同时日常我们只使用 char 保存英文字母、数字字符和英文符号,不要把 '中' 这样的中文汉字放进 char 里,因为一个中文汉字占多个字节,单个 char 装不下。

这里还可以顺便了解一个常识:计算机内存只认识数字,所以每个英文字符在底层都对应一个固定的整数编号,叫做 “ASCII 码”。比如 'A' 对应 65,'a' 对应 97,'0' 对应 48,因此 char 在底层也算作一种特殊的整数类型。

4. 布尔类型(bool)

布尔是英文 “boolean” 的音译,是以英国数学家乔治·布尔(George Boole)的名字来命名的。在程序中,有些数据表示的不是 “具体有多少”,而是 “是不是” 或 “成不成立”,比如用户是否已登录、任务是否已完成、考试是否及格。

这类只有两种状态的数据,在 C++ 中就使用 bool 类型来表示。bool 类型的值只有 2 个:true 表示 “真”,false 表示 “假”,书写时字母必须全部小写。

示例 4:使用 bool 类型

#include <iostream>

int main() {
    bool isLoggedIn = true;
    bool isFinished = false;
    std::cout << isLoggedIn << " " << isFinished;
    return 0;
}

运行结果如下。

1 0

分析:

从运行结果可以看出,isLoggedIn 的值是 true,isFinished 的值是 false,但屏幕上输出的却是 1 和 0。这是因为使用 std::cout 直接输出 bool 变量时,C++ 默认用数字 1 表示 true,用数字 0 表示 false。

整数类型家族与数据溢出

我们在阅读其他 C++ 代码时,可能还会见到 short、long、long long 等类型名。既然 int 已经能保存整数了,为什么 C++ 还要提供这么多整数类型呢?

这主要是为了适应不同大小的数值范围需求。常见整数类型的区别如下表所示。

常见整数类型
数据类型 常见大小 大致范围 使用建议
short(短整型) 2 个字节 -32768 ~ 32767 范围较小,日常较少单独使用
int(整型) 4 个字节 约 -21 亿 ~ +21 亿 最常用,普通整数统一优先使用
long(长整型) 4 或 8 个字节 随系统平台变化 跨平台大小不固定,大整数推荐用 long long
long long(超长整型) 8 个字节 约 -922 亿亿 ~ +922 亿亿 当整数可能超过 21 亿时使用

每种整数类型都有固定的取值上限。一旦存入的整数超出了该类型的最大范围,就会发生 “数据溢出”,算出意想不到的错误结果。我们先拿范围较小的 short 类型(最大值为 32767)来看一个例子。

示例 5:整数的数据溢出

#include <iostream>

int main() {
    short num = 32767;
    num = num + 1;
    std::cout << num;
    return 0;
}

运行结果如下。

-32768

分析:

short 类型的最大取值是 32767。当我们在 32767 的基础上再加 1 时,32768 超出了 short 能承受的上限,触发了数据溢出,结果直接绕回变成了负数 -32768。

对于整数溢出,程序在运行时通常不会给出任何报错提醒。因此,当遇到可能超过 21 亿的大整数,比如保存约 81 亿的全球总人口时,我们就不能再使用 int 了,而应该换用范围更大的 long long 类型。

示例 6:使用 long long 保存大整数

#include <iostream>

int main() {
    long long population = 8100000000LL;
    std::cout << population;
    return 0;
}

运行结果如下。

8100000000

分析:

long long population = 8100000000LL; 定义了一个超长整型变量来保存 81 亿。数字末尾加上的后缀 LL 用来告诉编译器这是一个 long long 类型的整数字面量。这里虽然写成小写的 ll 也可以,但更推荐写大写的 LL,以免与数字 1 看混。

此外,整数类型还可以细分为有符号(signed)和无符号(unsigned)两类。平时直接写 int 或 long long 默认就是有符号整数,可以表示正数、0 和负数。如果在前面加上 unsigned(如 unsigned int),则只能保存 0 和正整数。

初学阶段大家只需要记住一条简单的选型原则:普通整数优先使用 int,超过 21 亿的大整数使用 long long。不要因为年龄、人数不会为负就刻意改成 unsigned int,因为无符号数在减法中一旦小于 0(如计算 0 - 1),会瞬间绕回变成几十亿的巨大正数而引发错误。

至于不同类型在当前电脑上具体占用多少个字节,可以使用 sizeof 运算符直接查出来,现阶段不需要死记硬背。

常见问题

1. 如果想保存一串文字,比如姓名或一句话,应该使用什么数据类型?

前面学习的 char 类型只能保存单个字符,比如 'A'。如果需要保存 "Jack" 或 "Hello, lvyenet!" 这样的一串文字,应该使用标准库提供的 std::string 字符串类型,并在代码开头引入 <string> 头文件。

上一篇:

下一篇:

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号