2. 基本语法与数据类型:变量、常量、基本数据类型、类型转换、auto关键字

好,咱们正式开始接触C++的“血肉”。

上一章我们把环境搭好了,也跑通了第一个程序。但说实话,那个程序除了打印一句话,啥也干不了。真正的程序,是要处理数据的——数字、文字、开关状态,这些东西在C++里怎么表示?怎么存?怎么变?

这一章,我们就来把这些基础打牢。

2.1 变量:给数据起个名字

变量,说白了就是一块内存空间,我们给它起了个名字。你可以把它想象成一个带标签的盒子。盒子里能放什么东西,取决于盒子的类型。

#include <iostream>
int main() {
    int age = 25;          // 一个叫age的盒子,里面放整数25
    double price = 19.99;  // 一个叫price的盒子,里面放小数
    char grade = 'A';      // 一个叫grade的盒子,里面放一个字符
    return 0;
}

我个人习惯,变量名一定要见名知意。别用 abc 这种名字。你想想看,三个月后回头看代码,看到 int a = 5;,你还能记得这个 a 是干嘛的吗?

命名规范小贴士:
  • 变量名只能包含字母、数字、下划线
  • 不能以数字开头
  • 不能是C++关键字(比如 intreturn
  • 推荐用驼峰命名法:studentAgetotalScore

2.2 常量:不变的值

有些数据,一旦确定就不该被修改。比如圆周率3.14159,或者程序里定义的最大人数。

C++里定义常量有两种方式:

// 方式一:const 关键字(推荐)
const double PI = 3.14159;
const int MAX_STUDENTS = 100;

// 方式二:#define 宏定义(C语言风格,不推荐)
#define MAX_SIZE 1024

我建议你优先用 const。为什么?因为 const 有类型检查,编译器能帮你发现错误。而 #define 只是简单的文本替换,出了问题很难排查。我曾经在一个项目里看到有人用 #define 定义了一个常量,结果因为宏展开的优先级问题,导致计算结果完全不对……嗯,从那以后我再也不用 #define 定义常量了。

2.3 基本数据类型

C++里最常用的四种基本类型,我列个表给你看:

类型 关键字 占用空间 取值范围 示例
整型 int 4字节 -21亿 ~ 21亿 int count = 10;
浮点型 float 4字节 约 ±3.4e38 float pi = 3.14f;
双精度浮点 double 8字节 约 ±1.8e308 double price = 99.99;
字符型 char 1字节 -128 ~ 127 char ch = 'A';
布尔型 bool 1字节 true / false bool isOK = true;
重点提醒:

float 类型时,数值后面要加 f 后缀。比如 3.14f。不加的话,编译器默认当成 double,可能会产生精度警告。我刚开始学的时候就踩过这个坑。

2.4 类型转换

实际开发中,不同类型的数据经常需要混着用。比如整数和浮点数做运算,或者把字符转成整数。

C++里类型转换分两种:

2.4.1 隐式类型转换(自动转)

int a = 10;
double b = a;  // int 自动转成 double,没问题
// 结果是 10.0

double x = 3.14;
int y = x;     // double 转 int,小数部分被截断!
// 结果是 3,不是 3.14

看到了吗?隐式转换虽然方便,但可能会丢失精度。从 doubleint,小数点后面的东西就没了。这个要特别小心。

2.4.2 显式类型转换(强制转)

如果你明确知道自己在做什么,可以用强制转换:

double pi = 3.14159;
int intPi = (int)pi;          // C风格:直接在前面加括号写类型
int intPi2 = static_cast<int>(pi);  // C++风格:推荐用这个

我个人强烈推荐用 static_cast。为什么?因为C风格的强制转换太“暴力”了,什么都能转,容易掩盖真正的错误。而 static_cast 至少会做基本的类型检查,更安全。

避坑指南:

我曾经在项目里看到有人用 (int*) 把一个 float 的地址强行转成 int* 来读取数据。结果因为浮点数和整数的内存表示完全不同,读出来的数值完全不对。这种“骚操作”千万别学。

2.5 auto关键字:让编译器帮你推类型

C++11 引入了 auto 关键字。它的作用是让编译器根据初始值自动推导变量类型。

auto age = 25;          // 编译器推导出 int
auto price = 19.99;     // 推导出 double
auto grade = 'A';       // 推导出 char
auto isPass = true;     // 推导出 bool

你可能会问:这有什么用?我直接写 int 不就行了?

嗯,在简单场景下确实区别不大。但当你遇到复杂的类型时——比如迭代器、lambda表达式——auto 能省下大量打字时间,而且让代码更清晰。

// 没有 auto 的时候
std::vector<int>::iterator it = vec.begin();

// 有了 auto 之后
auto it = vec.begin();  // 简洁多了

不过要注意,auto 必须在定义时初始化。你不能写 auto x; 然后后面再赋值——编译器不知道它是什么类型。

我的使用习惯:

对于简单类型(int、double、char),我一般直接写类型名,因为一眼就能看出是什么。但对于复杂类型(迭代器、模板类型),我会用 auto,让代码更简洁。说白了,auto 是个好工具,但别滥用。

知识体系总览

这一章的内容比较多,我画了一张图帮你理清关系:

基本语法与数据类型 变量 命名规则、初始化 常量 const / #define 基本数据类型 int, float, char, bool 类型转换 隐式 / 显式转换 auto关键字 类型自动推导 常见陷阱 精度丢失、类型混用 每个知识点都配有代码示例和避坑指南

这一章的内容,说白了就是C++的“砖瓦”。变量和常量是存数据的容器,基本类型决定了容器能装什么,类型转换让你能在不同容器间倒腾数据,而 auto 则是帮你偷懒的利器。

把这些基础打牢了,后面学函数、类、指针的时候,你才不会觉得吃力。嗯,下一章我们就要开始玩“运算符”了——加减乘除、逻辑判断,让程序真正动起来。


公众号:蓝海资料掘金营,微信deep3321