NOI C++ 课程体系 / 语法入门 / 第2讲
CSP-J 入门级 · 语法入门 · 基本数据类型专题

C++ 基本数据类型 完全指南

给每一种数据找到最合适的"容器" —— int、double、char、bool 逐一讲透,short、long long、float、byte 一个不落,溢出与精度陷阱一次看清。

6 大教学模块 8 种类型精讲 5 个精讲案例 5 大易错点 1 张速查表 15 道分层练习
本讲 · 第 6/56 讲基本数据类型
模块 01

情景导航

先用"装数据"的故事和生活类比建立直觉,再给出数据类型的准确定义,最后用一句口诀帮你快速选对类型。

故事故事引入 —— 小强的"容器"难题

编程课的第一天,老师带来了三个数据:班号 45、圆周率 3.1415926… 和字母 'A',让大家想办法把它们存进计算机里。

小强想了想说:"这还不简单?统统按数字存起来不就行了!"

老师笑了笑,拿出了三样东西:一个火柴盒、一个水杯和一个大水缸。"如果要装一滴水,你用什么?""当然是小杯子。""那要装一百斤大米呢?""得用麻袋或者粮仓!""寄一封信呢?""用信封!"

"计算机的内存就像一个大仓库,数据就是各式各样的货物。你会用火柴盒去装大米吗?"

小强恍然大悟:原来存数据也要"看货选容器"——班号 45 是整数,放进一个不大不小的"整数盒";圆周率有小数点,得用能装小数的"实数罐";字母 'A' 只有一个字符,一张小小的"字符邮票"就够了。

这种给数据挑选"容器"的学问,在编程里有一个正式的名字——数据类型。

💡 这个故事告诉我们什么?

容器不是越大越好:用火柴盒装不下大米,用水缸装一滴水又太浪费。数据也一样:

数据类型就是数据的"容器"。它规定了数据占多大内存、能表示多大的范围、能参与哪些运算。选对类型,程序才能又准确又省空间。

接下来的知识探究,我们就来认识 C++ 为我们准备好的 8 位"容器明星"。

类比生活类比 —— 容器、尺子、邮票与开关

把每种类型和身边的物品对一对号,你会发现它们的特点一下子就清晰了:

🥤

杯子 · 水桶 · 水缸

都是整数,容量却不同:short 是小杯子,int 是水桶,long long 是大水缸。容器越大,能装的数越大,占的内存也越多。

对应:short / int / long long
📏

刻度尺与精密天平

刻度尺只能读出整厘米(整数),精密天平却能读到 0.001 克(小数)。带小数点的数,需要 float 或 double 来装。

对应:int 与 float / double 的分工
✉️

一枚字符邮票

邮票上只印一个图案。char 就是专门存放一个字符的小容器,而且它内部存的其实是字符的编号(ASCII 码)。

对应:char
🔦

电灯开关

开关只有"开"和"关"两种状态。bool 也只有 true 和 false 两个值,专门用来记录"是否通过""是否成立"这类判断结果。

对应:bool
定义什么是数据类型

在 C++ 中,每个变量都必须先声明类型再使用。数据类型从三个方面对数据做出规定:

规定内容说明例子
占用的内存大小每种类型固定占用若干字节(Byte)int 通常占 4 字节
能表示的取值范围超出范围就会发生"溢出",结果出错int 最大约 21 亿
能参与的运算不同类型支持的运算不一样整数能求余 %,小数不能

C++ 的基本数据类型家族可以分为四大类:整数类型(short、int、long、long long)、实数类型(float、double)、字符类型(char)和布尔类型(bool)。本节课就把最常用的 8 位成员逐个讲透彻。

类型选择口诀 整数默认用 int,范围不够 long long 请;
小数少量 float 行,讲究精度 double 顶;
单个字符 char 装,是真是假 bool 扛;
先看范围再定型,溢出失真找不上。

还有一个经常听到的名字 byte——它主要是内存的计量单位,而不是常用的变量类型。它的真实身份,我们在模块二里专门揭晓。

模块 02

知识探究

逐一讲透 8 位"容器明星":整数三兄弟、实数两姐妹、char 与 bool,以及 byte 的真实身份;最后用 5 个案例揭开溢出与精度的陷阱。

1数据类型家族总览

C++ 基本数据类型家族共有四大支系、八位核心成员:

🔢 整数家族 —— 专门存放整数的容器
  • short:小杯,占 2 字节
  • int:绝对主力,占 4 字节
  • long:很多环境与 int 相同,占 4 字节
  • long long:大水缸,占 8 字节
📐 实数家族 —— 专门存放小数的容器
  • float:单精度,占 4 字节,约 7 位有效数字
  • double:双精度,占 8 字节,约 15~16 位有效数字
🔤 字符类型 —— 一枚字符邮票
  • char:占 1 字节,存一个字符,实际存的是 ASCII 码
🔦 布尔类型 —— 一个电灯开关
  • bool:占 1 字节,只有 true / false 两个值
类型占用字节表示范围一句话特点
short2-32768 ~ 32767整数小杯,小范围够用
int4约 -21 亿 ~ 21 亿整数首选,用得最多
long4(常见竞赛环境)与 int 相同很多环境里和 int 一样大
long long8约 -9.2×10¹⁸ ~ 9.2×10¹⁸大数必备,防止溢出
float4约 7 位有效数字单精度,小数容易失真
double8约 15~16 位有效数字小数首选,竞赛标配
char1一个字符(ASCII 码)装 'A'、'9' 这样的单个字符
bool1true / false记录判断结果
注意:C++ 标准只规定了每种类型的"最小尺寸"(例如 int 至少 2 字节),上表是常见竞赛环境(Dev-C++,32/64 位系统)中的实际情况。到底占几个字节,可以用 sizeof 现场测量。
2整数家族:short / int / long long

整数是竞赛中使用频率最高的类型。三兄弟的区别只在"容量":

类型声明示例范围适用场景
shortshort age = 12;-32768 ~ 32767年龄、分数等小范围整数(竞赛中较少单独使用)
intint score = 100;-2147483648 ~ 2147483647绝大多数整数的默认选择
long longlong long dist = 10000000000LL;约 -9.2×10¹⁸ ~ 9.2×10¹⁸乘积、累加、超过 21 亿的大数
C++声明三个整数变量
#include <iostream>
using namespace std;
int main()
{
    short s = 32000;
    int n = 2100000000;
    long long big = 9000000000LL;  // 超过 int 范围的数字要加 LL 后缀
    cout << s << " " << n << " " << big << endl;
    return 0;
}
运行结果
32000 2100000000 9000000000

解读:int 最多装到 2147483647(约 21 亿),9000000000 已经超出它的容量,必须交给 long long。写超出 int 范围的常数时,数字后面要加 LL 后缀,否则这个数本身就会先溢出。

3实数家族:float / double

带小数点的数统称实数(浮点数)。C++ 提供两种"精度档位":

类型占用字节有效数字特点
float4约 7 位单精度,位数一多就开始失真
double8约 15~16 位双精度,竞赛中的默认选择
C++用 double 计算圆的面积
#include <iostream>
using namespace std;
int main()
{
    double r = 2.5;
    double pi = 3.141592653589793;
    double s = pi * r * r;
    cout << s << endl;
    return 0;
}
运行结果
19.635
重要:在 C++ 中,像 3.14 这样的小数字面量,默认类型是 double。如果写 float f = 3.1415926;,实际上是先按 double 生成这个数,再"缩水"放进 float,精度悄悄丢失。竞赛中小数一律优先用 double。
4字符类型 char 与布尔类型 bool
🔤 char —— 存字符,其实存的是编号
  • 'A' 实际存的是 65,'a' 是 97,'0' 是 48(ASCII 码)
  • 字符用单引号括起来,且只能放一个字符
  • 因为存的是数字,字符也能参与加减运算
🔦 bool —— 只记录"是否"
  • 只有两个值:true(真,当作 1)与 false(假,当作 0)
  • 比较表达式(如 a > b)的结果就是 bool
  • 参与运算时遵循"非 0 即真,0 为假"
C++char 与 bool 小实验
#include <iostream>
using namespace std;
int main()
{
    char ch = 'A';
    bool ok = 10 > 3;
    cout << ch << endl;        // 输出字符本身
    cout << ch + 1 << endl;    // 字符参与运算,输出 ASCII 码
    cout << ok << endl;        // bool 输出 1 或 0
    return 0;
}
运行结果
A
66
1

解读:'A' + 1 得到 66(即 'B' 的编号),说明字符在内存里就是数字;bool 变量输出时显示 1(真)或 0(假)。

5byte 的真实身份

很多同学会问:老师,类型清单里怎么还有 byte?其实 byte 有两重身份,要分清楚:

身份一:内存的计量单位(最常用)
  • 1 字节(Byte,简写 B)= 8 个二进制位(bit)
  • 内存大小、文件大小都用字节来计量
  • 我们说"int 占 4 字节",指的就是这个 byte
身份二:C++17 的 std::byte(了解即可)
  • 它不是用来做算术的类型
  • 专门表示"原始字节数据",如一段内存快照
  • 入门与竞赛阶段完全用不到
记住:在课堂和竞赛里,byte 主要是单位名,不是常用的变量类型。真正的"类型明星"是 short、int、long long、float、double、char、bool 这几位,而每种类型占几个字节(byte),用 sizeof 一测便知。
案例5 个由浅入深的案例

案例 1:用 sizeof 测量 8 种类型的大小

题目:一次性输出 short、int、long、long long、float、double、char、bool 各占多少字节。

C++sizeof 测大小
#include <iostream>
using namespace std;
int main()
{
    cout << "short: " << sizeof(short) << endl;
    cout << "int: " << sizeof(int) << endl;
    cout << "long: " << sizeof(long) << endl;
    cout << "long long: " << sizeof(long long) << endl;
    cout << "float: " << sizeof(float) << endl;
    cout << "double: " << sizeof(double) << endl;
    cout << "char: " << sizeof(char) << endl;
    cout << "bool: " << sizeof(bool) << endl;
    return 0;
}
运行结果(常见竞赛环境)
short: 2
int: 4
long: 4
long long: 8
float: 4
double: 8
char: 1
bool: 1

解读:sizeof 是"测量容器"的工具,写法是 sizeof(类型) 或 sizeof(变量)。它返回的字节数正好印证了家族总览表。

案例 2:整数溢出 —— 水缸装满了会怎样

题目:给 int 装进它的最大值,再加 1,会发生什么?

C++整数溢出演示
#include <iostream>
using namespace std;
int main()
{
    int a = 2147483647;      // int 的最大值
    cout << a + 1 << endl;   // 再加 1
    long long b = 2147483647LL;
    cout << b + 1 << endl;   // 换 long long 试试
    return 0;
}
运行结果
-2147483648
2147483648

🎬 动画演示:整数溢出的"绕圈"过程

1
int 的最大值 2147483647,32 个二进制位已到极限
2
再加 1,最高位被迫进位
3
32 位变成 11111111111111111111111111111111
4
最高位是符号位,被解读为负数 -2147483648 —— 溢出"绕圈"了!

解读:int 装满之后再进位,会像表盘一样绕回到负数一侧,程序不会报错,错误悄悄发生。解决办法只有一个:提前换大容器——预感数字会很大时,直接声明 long long。竞赛中两个 10 万级别的数相乘(100000 × 100000 = 100 亿)就已经超过 int,必须用 long long。

案例 3:小数精度陷阱 —— float 与 double 的差距

题目:把圆周率 3.141592653589793 分别存进 float 和 double,输出对比。

C++精度对比
#include <iostream>
using namespace std;
int main()
{
    float f = 3.141592653589793;
    double d = 3.141592653589793;
    cout.precision(16);   // 让输出显示更多位数
    cout << f << endl;
    cout << d << endl;
    return 0;
}
运行结果
3.141592741012573
3.141592653589793

解读:float 只有约 7 位有效数字,从第 8 位开始就是"编造"的数字;double 则完整保留了 15~16 位。所以小数一律用 double。另外,两个小数比较是否相等时,不要直接写 a == b,而应该判断它们的差是否足够小(如 abs(a - b) < 1e-9)。

案例 4:字符与 ASCII 码 —— 字母会算术

题目:从字母 'A' 出发,用算术方法走到 'D',再把小写 'a' 变成大写。

C++字符算术
#include <iostream>
using namespace std;
int main()
{
    char c1 = 'A' + 3;      // 65 + 3 = 68,即 'D'
    char c2 = 'a' - 32;     // 97 - 32 = 65,即 'A'
    cout << c1 << endl;
    cout << c2 << endl;
    cout << (int)'0' << endl; // 字符 '0' 的编号
    return 0;
}
运行结果
D
A
48

解读:记住三个锚点:'A' = 65,'a' = 97,'0' = 48;大写变小写加 32,小写变大写减 32。大小写转换、字母移位这类题目都靠它。

案例 5:bool 实战 —— 让计算机做判断

题目:把比较结果存进 bool 变量,观察它的输出。

C++bool 判断
#include <iostream>
using namespace std;
int main()
{
    bool b1 = 7 > 5;
    bool b2 = (3 + 4 == 8);
    int x = (9 < 2);
    cout << b1 << endl;
    cout << b2 << endl;
    cout << x << endl;
    return 0;
}
运行结果
1
0
0

解读:true 输出 1,false 输出 0。bool 的结果还能存进 int(真变 1,假变 0),反过来任何非 0 的数都会被当作"真"。这个特性在写 if 判断时非常好用,后面的课程会见到它大显身手。

模块 03

实践应用

三道动手题:给数据选类型、给代码捉虫子、给内存算账目。先自己做,再点开答案对照。

实践 1 类型选择

题目:选容器大师 —— 给下面的数据各挑一个最合适的类型

数据你的选择
班级人数 45?
圆周率(要求保留 15 位有效数字)?
等级字符 'A'?
本次考试是否及格?
地球到月球的距离 384400(千米)?
999999 × 999999 的乘积?
提示:先问两个问题——它是整数、小数、字符还是判断结果?数值会不会超过 21 亿?
点击查看参考答案
数据推荐类型理由
班级人数 45int小整数,int 绰绰有余
圆周率(15 位有效数字)doublefloat 只有约 7 位,装不下 15 位
等级字符 'A'char单个字符专用容器
是否及格bool只有"是 / 否"两种结果
地月距离 384400int远小于 21 亿,无需大容器
999999 × 999999 的乘积long long乘积约 10¹²,超过 int 的 21 亿上限
说明:选类型就是"看数据下菜碟"。只要涉及乘积、累加,就要警惕结果是否超过 int 范围。
实践 2 捉虫挑战

题目:下面三行代码各藏着一只"虫子",找出来并改正

C++有问题的三行代码
int pi = 3.1415926;          // 第 1 行
int s = 100000 * 100000;     // 第 2 行
char ch = "A";               // 第 3 行
点击查看参考答案
第 1 行:用 int 装小数,小数部分会被整段丢弃,pi 变成 3。应改为 double pi = 3.1415926;
第 2 行:100000 × 100000 = 100 亿,超过 int 的 21 亿上限,发生溢出得到错误结果。应改为 long long s = 100000LL * 100000;(注意:只把左边的 s 声明为 long long 是不够的,乘法发生时两个 int 已经先溢出了)。
第 3 行:双引号表示字符串,char 只能装单个字符,要用单引号。应改为 char ch = 'A';
实践 3 内存小会计

题目:下面的变量一共占多少内存?

C++变量清单
int a;
double b;
char c;
bool d;
long long e;

问题 1:这 5 个变量一共占用多少字节?
问题 2:换算成二进制位(bit)是多少?
问题 3:1000 组这样的变量,大约占多少 KB?(1 KB = 1024 字节)

点击查看参考答案
问题 1:int 4 + double 8 + char 1 + bool 1 + long long 8 = 22 字节。
问题 2:1 字节 = 8 位,22 × 8 = 176 位。
问题 3:22 × 1000 = 22000 字节,22000 ÷ 1024 ≈ 21.5 KB。看,选对类型、心里有本"内存账",是优秀程序员的基本功。
模块 04

总结提升

把 8 种类型浓缩成一张表、一句口诀,再用一个经典陷阱题检验你是否真正学会了选型。

总结核心要点总结
类型字节范围 / 精度使用要诀
short2-32768 ~ 32767小范围整数,竞赛中少用
int4约 ±21 亿整数默认首选
long long8约 ±9.2×10¹⁸大数、乘积必备,常数加 LL
float4约 7 位有效数字精度不足,竞赛基本不用
double8约 15~16 位有效数字小数默认首选
char1一个字符(ASCII 码)单引号、单字符;A=65 a=97 '0'=48
bool1true / false输出 1 或 0,非 0 即真
byte—1 字节 = 8 位是计量单位,不是常用变量类型
类型选择口诀(再背一遍) 整数默认用 int,范围不够 long long 请;
小数少量 float 行,讲究精度 double 顶;
单个字符 char 装,是真是假 bool 扛;
先看范围再定型,溢出失真找不上。
拓展拓展案例 —— 整数除法的经典陷阱

同样是"5 除以 2",写法不同,结果天差地别:

C++一题三解:5 ÷ 2
#include <iostream>
using namespace std;
int main()
{
    int a = 5 / 2;
    double b = 5.0 / 2;
    double c = (double)5 / 2;
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;
    return 0;
}
运行结果
2
2.5
2.5

解读:两个整数相除,结果还是整数,小数部分直接砍掉;只要有一方是 double(写 5.0 或用 (double) 强制转换),结果就带小数。求平均数、算比例时,这个陷阱出现频率极高。

🧠 思考与启发

为什么 C++ 不干脆发明一种"超级容器"类型,什么数据都能装、要多大范围有多大范围?

提示:想一想内存的成本、运算的速度,以及"用大水缸装一滴水"的浪费。计算机资源是有限的,用合适的工具做合适的事,这正是工程思维的第一课——选型。

模块 05

学习检测

5 个最容易丢分的陷阱、一张考前必背速查表,以及可以贴在文具盒上的知识点笔记。

易错 1

整数除法把小数偷偷丢掉

两个整数相除,结果仍是整数,小数部分被直接截断。

错误写法
double x = 5 / 2;   // x = 2
正确写法
double x = 5.0 / 2; // x = 2.5
口诀:想要小数,相除的两数中至少一个得是实数。
易错 2

int 装不下,溢出绕圈

乘积或累加结果超过 21 亿,int 会悄悄溢出成错误的数,程序不会报错。

错误写法
int s = 100000 * 100000; // 溢出
正确写法
long long s = 100000LL * 100000;
口诀:先定类型再计算,大数要用 long long。
易错 3

用 float 存小数,精度悄悄丢失

float 只有约 7 位有效数字,位数一多就开始"编造"。

错误写法
float pi = 3.141592653589793;
正确写法
double pi = 3.141592653589793;
口诀:竞赛小数,一律 double。
易错 4

char 的单引号写成双引号

双引号表示字符串,char 只能装一个用单引号括起来的字符。

错误写法
char ch = "A";
正确写法
char ch = 'A';
口诀:单字符,单引号;双引号,是字符串。
易错 5

超大常数直接赋给 int

常数本身超过 int 范围,还没赋给变量就已经溢出,编译器可能报错也可能给出错误值。

错误写法
int n = 2147483648;
正确写法
long long n = 2147483648LL;
口诀:超过 21 亿的数字,long long 加 LL 后缀才保险。
速查考前速查表
类型关键字字节范围 / 精度常用场景
短整型short2-32768 ~ 32767小范围整数
整型int4-2147483648 ~ 2147483647绝大多数整数
长长整型long long8约 ±9.2×10¹⁸大数、乘积、累加
单精度实数float4约 7 位有效数字了解即可,少用
双精度实数double8约 15~16 位有效数字所有小数运算
字符型char1一个字符(ASCII 码)'A'、'9' 等单字符
布尔型bool1true / false判断结果
字节(单位)byte1 = 8 bit—内存计量单位
📌知识点速记卡
先声明后使用

每个变量必须先写类型再使用:int a; double b; 这是 C++ 的硬性规定。

范围要背牢

int 约 ±21 亿;short 约 ±3.2 万;long long 约 ±9.2×10¹⁸。

溢出会绕圈

int 最大值加 1 变成最小负数,程序不报错,错误最隐蔽。

精度有高低

float 约 7 位,double 约 15~16 位;竞赛小数全部用 double。

ASCII 三锚点

'A' = 65,'a' = 97,'0' = 48;大小写互转加减 32。

bool 两状态

true 输出 1,false 输出 0;运算时非 0 即真。

byte 是单位

1 Byte = 8 bit;说"占几个字节"用的就是它,不是常用变量类型。

小数字面量默认 double

写 3.14 时它就是 double;float f = 3.14; 会经历一次"缩水"。

课后练习

练习作业

巩固八种基本数据类型的选择与使用,分层练习,点击展开答案与解析。

总结练习3 道综合题
总结 1 判断题

题目:判断 —— short 类型可以存放 50000。

想一想 short 的取值范围。

提示:short 只有 2 个字节,范围是 -32768 ~ 32767。
点击查看参考答案
答案:错误。50000 超过了 short 的最大值 32767,强行存放会溢出。应当使用 int。
总结 2 计算题

题目:cout << sizeof(double) * 2; 的输出结果是多少?

先想 double 占几个字节,再乘 2。

点击查看参考答案
答案:16。double 占 8 字节,8 × 2 = 16。注意 sizeof 的结果是整数,参与的是普通乘法。
总结 3 编程题

题目:声明 int、double、char、bool 四个变量并赋初值,分别输出它们的值和所占字节数。

要求一行输出值、一行输出 sizeof 结果。

提示:用 sizeof(变量名) 测字节数,cout 可以连续输出。
点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main()
{
    int a = 12;
    double b = 3.14;
    char c = 'X';
    bool d = true;
    cout << a << " " << b << " " << c << " " << d << endl;
    cout << sizeof(a) << " " << sizeof(b) << " " << sizeof(c) << " " << sizeof(d) << endl;
    return 0;
}
参考输出:第一行 12 3.14 X 1,第二行 4 8 1 1(常见竞赛环境)。bool 的 true 输出为 1。
A 组基础巩固(4 题)
A1 默写题

题目:写出 int、short、long long 三种类型的取值范围。

写不出具体数字时,用"约多少亿"也可以。

点击查看参考答案
C++完整参考代码
// A1:用 numeric_limits 把三种类型的范围打印出来,和默写结果对照
#include <iostream>
#include <limits>
using namespace std;

int main()
{
    cout << "int       : " << numeric_limits<int>::min()
         << " ~ " << numeric_limits<int>::max() << endl;
    cout << "short     : " << numeric_limits<short>::min()
         << " ~ " << numeric_limits<short>::max() << endl;
    cout << "long long : " << numeric_limits<long long>::min()
         << " ~ " << numeric_limits<long long>::max() << endl;
    return 0;
}
/* 运行结果:
int       : -2147483648 ~ 2147483647
short     : -32768 ~ 32767
long long : -9223372036854775808 ~ 9223372036854775807
*/

答案:int:-2147483648 ~ 2147483647(约 ±21 亿);short:-32768 ~ 32767;long long:-9223372036854775808 ~ 9223372036854775807(约 ±9.2×10¹⁸)。

思路:整数范围由二进制位数决定:n 位有符号整数的范围是 -2ⁿ⁻¹ ~ 2ⁿ⁻¹-1。short 是 16 位 → ±32767;int 是 32 位 → ±21 亿;long long 是 64 位 → ±9.2×10¹⁸。记住「多一位翻一倍」,不必死背数字。

考点:本讲「整数家族 short / int / long long 的容量」——选类型的唯一依据就是取值范围。

易错:上限记对却把下限写成 -2147483647(应为 -2147483648,负数比正数多一个);误以为 long long 只有 32 位;以为 short 能装下 100000。

A2 判断题

题目:判断 —— float 的精度比 double 高。

从占用字节和有效数字两方面想。

点击查看参考答案
答案:错误。float 只有约 7 位有效数字,double 有约 15~16 位,double 精度更高。

考点:float 与 double 的精度差异——它们能保证的有效数字位数不同(float 约 7 位,double 约 15~16 位)。

易错:误以为 float 名字里没有 double 的份额就更精确,或以为 float 能存下更多位小数。

A3 问答题

题目:char 类型实际存储的是什么?为什么字符可以参与加减运算?

结合 ASCII 码回答。

点击查看参考答案
答案:char 实际存储的是字符的 ASCII 码(一个整数),例如 'A' 存的是 65。既然本质是整数,自然可以参与加减运算,'A' + 1 得到 66。

考点:char 在内存里存的是字符对应的 ASCII 码值,本质是一个整数。

易错:把 'A' 和 "A" 搞混(单引号是字符,双引号是字符串),或以为 'A' + 1 会得到字符串。

A4 读程序

题目:写出下面程序的输出结果。

C++读程序写结果
int x = 7;
bool b = x > 5;
cout << b << endl;
点击查看参考答案
C++完整参考代码
// A4:题目原程序
#include <iostream>
using namespace std;

int main()
{
    int x = 7;
    bool b = x > 5;        // 7 > 5 成立,b 为 true
    cout << b << endl;     // bool 输出时不显示 true/false,而是 1/0
    return 0;
}
// 实际输出:1

答案:输出 1。

思路:x > 5 先算出比较结果 true,再存进 bool b;cout 输出 bool 类型时不显示 true/false,而是用 1 表示真、0 表示假。

考点:本讲「bool 类型的取值与输出」。

易错:以为屏幕会打印 true;或把 bool b = x > 5; 误写成 bool b = x;(非 0 都是 true,只要 x 不为 0 输出就都是 1,掩盖了错误)。把 x 改成 3 后输出才是 0。

B 组能力提高(4 题)
B1 改错题

题目:int s = 100000 * 100000; 为什么会出错?请改正。

先算出乘积,再和 int 的上限比一比。

提示:100000 × 100000 = 100 亿。
点击查看参考答案
C++完整参考代码
// B1:先看错误的写法,再看改正后的写法
#include <iostream>
using namespace std;

int main()
{
    int bad = 100000 * 100000;              // 两个 int 相乘 → 溢出
    cout << "错误结果:" << bad << endl;     // 1410065408(不是 100 亿)

    long long good = 100000LL * 100000;     // 参与乘法的是 long long
    cout << "正确结果:" << good << endl;    // 10000000000
    return 0;
}

答案:乘积 100000 × 100000 = 100 亿(10¹⁰),超过 int 上限 2147483647,发生溢出,实际得到 1410065408。改正:long long s = 100000LL * 100000;,此时输出 10000000000。

思路:赋值号 = 从右往左算,先算 100000 * 100000。两个操作数都是 int,乘法就按 int 进行,中间结果已经溢出,等号左边是什么类型都救不回来。只要让参与乘法的数带上 LL 后缀,乘法才按 long long 计算。

考点:本讲「整数溢出与类型转换」——运算的「舞台」由操作数类型决定,不由接收变量决定。

易错:只写 long long s = 100000 * 100000; 就以为万事大吉,结果仍是 1410065408;或写成 (long long)(100000 * 100000),强制转换发生在溢出之后,同样无效。

B2 问答题

题目:说明 float 与 double 的区别,并解释竞赛中为什么几乎总是选择 double。

从字节数、有效数字、误差积累三个角度回答。

点击查看参考答案
答案:float 占 4 字节、约 7 位有效数字;double 占 8 字节、约 15~16 位有效数字。竞赛题目常涉及多步运算,误差会不断积累,float 的 7 位精度很容易导致答案失真;而 double 的精度足够,多花 4 字节内存完全值得,所以几乎总是用 double。

考点:浮点类型在内存占用与精度之间的权衡,竞赛中优先保证精度。

易错:认为 float 省一半内存所以更快更好;或以为换用 double 后小数运算就完全精确了。

B3 读程序与改写

题目:已知 char c = 'C'; 写出 cout << c + 2; 的输出;再改写语句,让屏幕输出字母 'E' 本身。

提示:'C' 的 ASCII 码是 67。

点击查看参考答案
C++完整参考代码
// B3:0 的本质是整数 67
#include <iostream>
using namespace std;

int main()
{
    char c = 'C';
    cout << c + 2 << endl;          // 字符参与算术 → 输出整数 69
    cout << (char)(c + 2) << endl;  // 强制转回 char → 输出字母 E
    return 0;
}
// 实际输出:
// 69
// E

答案:cout << c + 2; 输出数字 69;改写为 cout << (char)(c + 2); 才能输出字母 E。

思路:char 中存的其实是字符的 ASCII 码,'C' 就是 67。c + 2 是整数运算,得到 69,cout 按 int 打印所以是 69。想让它当字符显示,必须用 (char) 把 69 显式转回 char。

考点:本讲「char 的本质是整数」以及强制类型转换。

易错:写 cout << c + 2; 却期待看到 E;把 (char) 漏掉只写成 c + 2;或先存进 int 变量再输出,同样显示 69。

B4 场景选型

题目:为下列数据选择类型并说明理由:① 学号 20250201;② 身高 1.65(米);③ 性别字符 'M';④ 是否满分。

注意学号的位数。

点击查看参考答案
答案:① int(20250201 远小于 21 亿;若学号可能更长也可用 long long);② double(身高是小数);③ char(单个字符);④ bool(只有是否两种结果)。

考点:根据数据的取值范围和实际含义选类型:整型存整数、浮点存小数、char 存字符、bool 存真假。

易错:用 double 存学号,输出时变成科学计数法或末尾多出 .0;也容易把「是否满分」定义成 char。

C 组思维挑战(4 题)
C1 编程题

题目:编写完整程序,用 sizeof 测量并输出 short、int、long、long long、float、double、char、bool 八种类型的大小。

要求包含头文件、命名空间、主函数的完整结构,输出清晰易读。

提示:每种类型一行:cout << "int: " << sizeof(int) << endl;
点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main()
{
    cout << "short: " << sizeof(short) << endl;
    cout << "int: " << sizeof(int) << endl;
    cout << "long: " << sizeof(long) << endl;
    cout << "long long: " << sizeof(long long) << endl;
    cout << "float: " << sizeof(float) << endl;
    cout << "double: " << sizeof(double) << endl;
    cout << "char: " << sizeof(char) << endl;
    cout << "bool: " << sizeof(bool) << endl;
    return 0;
}
参考输出:2、4、4、8、4、8、1、1(常见竞赛环境,个别环境 long 为 8 也属正常)。

思路:sizeof 是求字节数的运算符,对八种类型各调用一次、按顺序往输出即可。

易错:把 sizeof 当普通函数写、漏掉类型外层的括号;另外 long 在不同平台可能是 4 字节也可能是 8 字节,答案本身不唯一。

C2 编程题

题目:2 的 40 次方等于 1099511627776。请写程序输出这个数,并解释为什么必须使用 long long。

可以先想一想:这个数是几位数?超过 21 亿了吗?

点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main()
{
    long long ans = 1099511627776LL;
    cout << ans << endl;
    return 0;
}
说明:1099511627776 约 1.1×10¹²,是 13 位数,远超 int 约 21 亿(2.1×10⁹)的上限,必须用 8 字节的 long long,并给常数加 LL 后缀。也可以用循环连乘 40 次,但连乘过程中间变量同样要声明为 long long。

思路:这个数有 13 位,远超 int 的表示范围,必须选 8 字节的 long long 才能装下。

易错:只把变量声明成 long long,常数却写成普通整数(不加 LL 后缀),运算仍按 int 进行而溢出。

C3 研究题

题目:为什么 0.1 + 0.2 的结果并不精确等于 0.3?请用自己的话解释,并写出判断两个小数"相等"的正确方法。

提示:计算机内部只有 0 和 1,小数也要换成二进制存放。

点击查看参考答案
答案:计算机用二进制存储小数,而 0.1、0.2 在二进制里是无限循环小数,只能截取有限位存放,本身就带有一点点误差;两个带误差的数相加,结果自然与 0.3 差一点点。所以比较两个小数是否相等,不能写 a == b,正确方法是判断差的绝对值是否足够小:abs(a - b) < 1e-9,足够小就认为相等。

思路:从「二进制无法精确表示 0.1、0.2」入手解释误差,再用两数差值的绝对值与 1e-9 比较来判断是否相等。

易错:直接用 a == b 判断两个小数相等;求绝对值时忘记包含 <cmath>,或把整型的 abs 用在 double 上。

C4 思考题

题目:bool 只有两个值,1 个二进制位就够用了,为什么它还要占 1 个字节(8 位)?

这是一道开放思考题,没有标准程序可写。

提示:想想内存是怎样被编号和访问的。
点击查看参考答案
参考思路:计算机内存是按"字节"为单位编号访问的,最小的可独立寻址单位就是 1 字节。如果 bool 只占 1 位,读取它时仍要先找到它所在的字节,处理起来反而更慢更复杂;用 1 字节存放,换取的是访问速度和实现的简洁。工程上常常用"一点空间换简单和速度",这就是权衡(trade-off)。

易错:误以为 bool 只占 1 个二进制位,其实 sizeof(bool) 等于 1 个字节,也就是 8 位。