C++ / ACM 自学笔记 · v5.0

(二) 变量、数据类型与初始化

如果同一程序需要保存人数、总费用、平均分和成绩等级,就不能只问“用哪个变量名”,还要问“数据有没有小数、最大可能是多少”。类型决定存储和运算规则,变量名表示题目中的角色。

1. 声明、初始化与赋值是不同动作

int count=3; 创建名为 count 的 int 变量,并用 3 初始化。之后 count=8; 给已有变量赋新值,不创建第二个 count。初始化发生在创建时,赋值发生在对象已经存在后。

题目原文(自拟): 程序无需输入。original 初值为 7,copy 初始化为 original 的值;把 original 改成 9,依次输出两个变量。

初始化复制当时的值,之后两个变量独立变化
#include <iostream>
using namespace std;

int main() {
    int original = 7;
    int copy = original; // 复制当前的整数值,不建立长期关联。
    original = 9;        // 只修改 original,copy 仍为 7。
    cout << original << ' ' << copy << '\n';
}

输出 9 7。把值复制到另一个变量后,修改来源不会自动同步;引用章节才会介绍让两名称访问同一个对象的方式。

写法 含义 结果
int x=0; 创建并初始化 x 的初值为 0
int x(0); 直接初始化 x 的初值为 0
int x{};、int x{0}; 花括号初始化 基本整数得到 0;有些窄化转换会被拒绝
int x; 创建普通局部整数,不提供初值 在成功赋值前不能读取
x=5; 修改已有变量 执行后 x 的值变为 5

普通局部 int x; 没有初值,成功输入或赋值后才有可用的数值。全局变量和 static 变量会先进行零初始化,static 的用法在函数章节继续讲。标识符区分大小写,score 与 Score 是两个名字;int、return 等关键字已经有语言规定的用途。

2. 从题目范围选择基本类型

类型 保存什么 常见比赛环境中的表示
int 整数、下标 常见比赛环境中为 32 位,约 \(-2.1\times10^9\) 到 \(2.1\times10^9\)
long long 更大的整数、累计和与乘积 至少 64 位;常见上界约 \(9.22\times10^{18}\),仍不能无限增大
double 带小数的近似值 小数通常不能精确表示;精度与范围是不同问题
char 单个字符或一个字节单元 'A'、'0' 与数字 0 不同;一个中文字符通常占多个 UTF-8 字节
bool 逻辑值 只有 true、false;默认输出为 1、0
unsigned int、unsigned long long 非负整数和位运算 没有负数;与有符号类型混合时要核对转换

先估算中间结果。 如果有 \(10^5\) 项,每项绝对值至多 \(10^9\),累计和的绝对值至多 \(10^{14}\),应选 long long;不能因为单项能放进 int,就把总和也放进 int。1 通常是 int 字面量,1LL 是 long long,1u 是 unsigned int,1ULL 是 unsigned long long。

sizeof(int) 返回 int 占用的字节数,sizeof(value) 查询对象大小。sizeof(char) 为 1,常见比赛环境中一个字节为 8 位。字节数描述存储大小,INT_MIN、INT_MAX 等常量则直接给出可保存的数值范围。

<climits> 提供整数范围常量,例如 INT_MIN、INT_MAX、LLONG_MAX,以及每字节的位数 CHAR_BIT。

题目原文(自拟演示): 程序无需输入,分三行输出 int 与 long long 的字节数、int 的下界与上界、long long 的上界与每字节的位数。

分析: 用 sizeof 查询类型占用的字节数,用 INT_MIN、INT_MAX、LLONG_MAX 查询整数范围,用 CHAR_BIT 查询每字节的位数。

#include <climits> // 声明范围常量;这里不需要模板知识。
#include <iostream>
using namespace std;

int main() {
    cout << sizeof(int) << ' ' << sizeof(long long) << '\n'; // 单位为字节。
    cout << INT_MIN << ' ' << INT_MAX << '\n';               // 当前实现的 int 范围。
    cout << LLONG_MAX << ' ' << CHAR_BIT << '\n';            // long long 上界和每字节位数。
}

在常见的 32 位 int、64 位 long long 环境中,输出如下:

4 8
-2147483648 2147483647
9223372036854775807 8

这些数值说明了类型能保存多大的数。做题时,再将题目中可能得到的最大结果与类型范围比较,就能决定用 int 还是 long long。模板章节还会介绍另一种查询工具 numeric_limits。

3. 单字符、文本与逻辑值

单引号写一个字符,例如 'A';双引号写文本,例如 "ABC"。字符 '0' 有自己的编码值,不是整数 0。十进制数字字符连续排列,因此已确认 ch 是数字字符后,可用 ch-'0' 得到对应数字。

题目原文(自拟演示): 程序无需输入。输出字符 A、数字字符 7 对应的数值,以及 false、true 的默认输出。

#include <iostream>
using namespace std;

int main() {
    char grade = 'A';
    char digit = '7';
    bool passed = true;
    cout << grade << ' ' << digit - '0' << '\n'; // 本例已保证 digit 是数字字符。
    cout << false << ' ' << passed << '\n';      // 默认得到 0 1。
}

输出为 A 7、0 1,各占一行。bool 的 false 表示假,true 表示真;条件判断中数字 0 转成假,非零转成真。需要输出 true/false 的文本时可用 boolalpha,输出格式章节会展示状态设置。

先区分整数、小数、字符与真假,再决定怎样计算。下一节重点解释“表达式先按什么类型算”,而不是只看接收结果的变量类型。

查阅笔记正文与全部题解 · Ctrl / ⌘ K