第二章 基础语法与数据类型
说实话,每次带新人入门C++,我都是从这一章开始讲起。为什么?因为变量和数据类型,说白了就是程序的「砖块」。你盖楼再厉害,砖块没选对,楼迟早要塌。我自己刚入行那会儿,就吃过类型转换的亏——嗯,后面我会细说。
2.1 变量声明与初始化
变量是什么?就是一块内存空间,我们给它起了个名字。C++里声明变量很简单,但初始化这件事,我建议你从一开始就养成好习惯。
int age; // 声明,但未初始化
int score = 90; // C风格初始化
int level(5); // 构造函数风格
int count{10}; // C++11 统一初始化(推荐)
核心原则:变量一定要初始化。未初始化的变量里存的是「垃圾值」,我曾经在调试一个内存泄漏时,发现罪魁祸首就是忘了初始化一个计数器。
我个人习惯用花括号 {} 初始化。为什么?因为它能防止窄化转换——比如 int x{3.14} 会直接报错,而 int x = 3.14 只会静默截断。你想想看,哪个更安全?
2.2 基本数据类型
C++ 的基本类型就那么几个,但每个都有它的脾气。
| 类型 | 大小(通常) | 取值范围 | 典型用途 |
|---|---|---|---|
int |
4 字节 | -2^31 ~ 2^31-1 | 整数计数、索引 |
float |
4 字节 | 约 ±3.4e38 | 单精度小数 |
double |
8 字节 | 约 ±1.8e308 | 高精度计算 |
char |
1 字节 | -128 ~ 127 或 0~255 | 单个字符 |
bool |
1 字节 | true / false | 逻辑判断 |
小技巧:浮点数比较时别用 ==。我踩过这个坑——两个看似相等的浮点数,因为精度问题就是不相等。用 fabs(a - b) < 1e-6 才靠谱。
2.3 常量与字面量
常量就是值不会变的变量。C++ 里有两种主流写法:
const double PI = 3.1415926; // 运行时常量
constexpr int MAX_SIZE = 1024; // 编译期常量(C++11起)
字面量就是你直接写在代码里的值。比如 42 是整数字面量,3.14f 是 float 字面量(注意那个 f),'A' 是字符字面量。
我记得有一次代码评审,看到有人写了 3.14 但没加 f,结果编译器把它当 double 处理,跟 float 变量运算时产生了隐式转换,性能白白损失。细节啊,朋友们。
2.4 类型转换
类型转换分两种:隐式和显式。隐式转换是编译器偷偷帮你做的,显式转换是你主动告诉编译器「听我的,转!」。
隐式转换
int a = 10;
double b = a; // int → double,安全
bool c = a; // 非零 → true,零 → false
隐式转换在「提升」时一般没问题(比如 int 到 double),但在「降级」时就要小心了。比如 double d = 3.14; int i = d;,小数部分直接丢了,编译器连个警告都不给。
注意:隐式转换是 C/C++ 里最容易埋坑的地方之一。我曾经在项目里遇到一个 bug,就是因为一个大整数被隐式转换成 short,结果数据溢出,整个系统行为变得诡异。排查了两天才找到原因。
显式转换
C++ 提供了四种命名的强制类型转换,比 C 风格的 (type)value 更安全、更明确:
double pi = 3.14159;
int approx = static_cast<int>(pi); // 最常用,编译时检查
const int* p = &someValue;
int* q = const_cast<int*>(p); // 去掉 const,慎用
// reinterpret_cast 用于底层位模式转换,极少用
// dynamic_cast 用于多态类型向下转换,后面章节会讲
我个人几乎只用 static_cast。它明确告诉读者和编译器:「我知道我在做什么,这里就是要转」。C 风格的强制转换太粗暴,容易掩盖问题。
知识体系总览
下面这张图把本章的核心知识点串了起来。你可以把它当作一张「地图」,学完后再回来看,会更有感觉。
我的建议:学数据类型,别死记硬背大小和范围。多写代码,多踩坑,自然就记住了。尤其是类型转换这块,我建议你每个都亲手试一遍,看看编译器会报什么错、运行时会发生什么。
好了,这一章就到这里。记住一句话:类型安全是 C++ 程序员的底线。初始化变量、谨慎转换、善用常量——这些习惯会让你少熬很多夜。
公众号:蓝海资料掘金营,微信deep3321