C/C++ 从零开始完整教程(小白也能看懂)
前面我们学了 JavaScript(前端)、Go(后端)、TypeScript(类型安全)。这一篇学C/C++——它们是编程世界的”地基”。
你可能听过这些说法:“C 是编程语言的祖师爷""操作系统是 C 写的""C++ 很难”。别被吓到,这一篇就用大白话讲清楚,保证你能看懂、能上手。
一、C 和 C++ 是什么?为什么值得学?
C:编程语言的祖师爷
C 语言是 1972 年由丹尼斯·里奇发明的,用来写 Unix 操作系统。它太成功了,以至于后来的 C++、Java、C#、Go 全都”借鉴”了它的语法。
C 的特点:
- 底层:能直接操作内存,贴近硬件
- 快:编译型语言,速度极快
- 广泛:操作系统、嵌入式、驱动程序、游戏引擎都在用
C++:给 C 加上了”面向对象”
C++ 是 1985 年由 Bjarne Stroustrup 在 C 的基础上发明的,”++“是 C 语言的”自增”运算符——意思是”比 C 更进一步”。
C++ 的特点:
- 完全兼容 C:会 C++ 就基本会 C
- 多了面向对象:类(class)、对象、封装、继承、多态
- 应用广:游戏(虚幻引擎)、高性能软件、浏览器内核、数据库
和之前学的语言对比
| 语言 | 类型 | 特点 |
|---|---|---|
| JavaScript | 解释型 | 跑在浏览器,灵活 |
| Go | 编译型 | 后端服务,并发强 |
| Python | 解释型 | 写起来快,AI 常用 |
| C/C++ | 编译型 | 最快、最底层,但要手动管内存 |
一句话: C/C++ 让你真正理解”计算机是怎么运行的”。学了它,你再看别的语言会豁然开朗。
二、先装环境:让代码跑起来
C/C++ 写好后要编译成电脑能直接执行的程序。我们需要一个编译器。
Windows:装 MinGW 或 Visual Studio
最简单的方式是装 Dev-C++ 或 Code::Blocks,它们自带编译器,装完就能用。
macOS
# 安装命令行工具(自带 clang 编译器)xcode-select --installLinux
# Ubuntu / Debiansudo apt updatesudo apt install g++验证安装
打开终端:
g++ --version能看到版本号就装好了。g++ 是 C++ 的编译器,gcc 是 C 的编译器,clang++ 是另一套(macOS 默认)。
三、第一个程序:Hello World
新建文件 hello.cpp(C++ 用 .cpp 后缀,C 用 .c):
#include <iostream> // 引入输入输出库
int main() { // 程序入口,main 是主函数 std::cout << "你好,世界!" << std::endl; // 输出一行 return 0; // 返回 0 表示程序正常结束}编译并运行
g++ hello.cpp -o hello # 编译,生成可执行文件 hello./hello # 运行# 输出:你好,世界!两个步骤拆解:
g++ hello.cpp -o hello:把源代码编译成可执行文件./hello:运行它
第一次看这段代码你可能很懵,逐个解释:
| 代码 | 意思 |
|---|---|
#include <iostream> | 引入标准库(类似”借用别人的工具”) |
int main() | 主函数,程序从这里开始跑 |
std::cout << "..." | 输出文字(cout 读作 “see-out”) |
std::endl | 换行 |
return 0; | 结束程序,返回 0 表示成功 |
和 JavaScript 对比:
- JS:
console.log("你好") - C++:
std::cout << "你好" << std::endl;
简化写法
写 using namespace std; 之后就不用每次都打 std:: 了:
#include <iostream>using namespace std; // 告诉编译器"我要用标准命名空间"
int main() { cout << "你好,世界!" << endl; return 0;}初学阶段推荐这种写法,代码短一点,更好读。
四、变量和数据类型
声明变量:必须先写类型
C++ 是强类型语言,变量必须声明类型:
#include <iostream>using namespace std;
int main() { int age = 18; // 整数 double price = 3.14; // 小数(双精度) char grade = 'A'; // 单个字符(用单引号) string name = "小明"; // 字符串(用双引号) bool isOK = true; // 布尔
cout << "年龄:" << age << endl; cout << "分数:" << price << endl; cout << "等级:" << grade << endl; cout << "名字:" << name << endl; cout << "是否正确:" << isOK << endl; return 0;}和 JS 最大的区别: JS 用 let 随便写,C++ 必须写清类型(int、double、string…)。这也是 C++ 更”严格”的原因——编译器会检查类型对不对。
常用类型速查
| 类型 | 说明 | 例子 |
|---|---|---|
int | 整数 | 18, -5 |
double | 小数(双精度) | 3.14159 |
float | 小数(单精度,更省空间) | 3.14 |
char | 单个字符 | ’A’ |
string | 字符串(需 #include <string>) | “你好” |
bool | 布尔 | true / false |
long long | 大整数 | 9000000000 |
常量的两种写法
// 方式一:const 关键字(推荐)const double PI = 3.14159;
// 方式二:#define 宏(C 的老写法)#define MAX 100常量一旦定义不能修改,防止不小心改错。
五、输入:让程序跟你对话
用 cin(读作 “see-in”)接收用户输入:
#include <iostream>using namespace std;
int main() { string name; int age;
cout << "请输入名字:"; cin >> name;
cout << "请输入年龄:"; cin >> age;
cout << "你好," << name << ",你今年" << age << "岁!" << endl; return 0;}运行后程序会停下来等你输入,输入完回车,程序继续。
注意: cin >> 遇到空格会停下(它把空格当分隔),所以输入”张三 李四”只会取到”张三”。要读一整行(含空格)用 getline:
string fullName;cout << "请输入完整名字:";getline(cin, fullName); // 读取一整行cout << "你输入的是:" << fullName << endl;六、条件判断:if / else
#include <iostream>using namespace std;
int main() { int score; cout << "请输入成绩:"; cin >> score;
if (score >= 90) { cout << "优秀!" << endl; } else if (score >= 60) { cout << "及格" << endl; } else { cout << "不及格" << endl; } return 0;}和 JS 很像,只是判断条件要加括号(if (score >= 90))。
switch:多分支选择
#include <iostream>using namespace std;
int main() { int day; cout << "输入星期几(1-7):"; cin >> day;
switch (day) { case 1: cout << "周一" << endl; break; case 2: cout << "周二" << endl; break; case 3: cout << "周三" << endl; break; case 4: cout << "周四" << endl; break; case 5: cout << "周五" << endl; break; case 6: cout << "周六" << endl; break; case 7: cout << "周日" << endl; break; default: cout << "输入错误" << endl; break; } return 0;}每个 case 结尾的 break; 不能漏,漏了会”穿透”到下一个 case 继续执行。
七、循环:for 和 while
#include <iostream>using namespace std;
int main() { // for 循环:数 1 到 5 for (int i = 1; i <= 5; i++) { cout << i << " "; } cout << endl; // 输出:1 2 3 4 5
// while 循环 int n = 0; while (n < 3) { cout << "第" << n << "次" << endl; n++; }
// do-while:至少执行一次 int m = 10; do { cout << "执行一次" << endl; m++; } while (m < 3);
return 0;}for 三部分: for (初始化; 条件; 每次递增)。和 JS 几乎一模一样。
break 和 continue:
break:跳出整个循环continue:跳过本次循环,进入下一次
for (int i = 1; i <= 10; i++) { if (i == 3) continue; // 跳过 3 if (i == 6) break; // 到 6 就停 cout << i << " ";}// 输出:1 2 4 5八、函数:把代码装进”盒子”
基本写法
C++ 函数要先”声明类型”:
#include <iostream>using namespace std;
// 声明一个函数:接收两个 int,返回 intint add(int a, int b) { return a + b;}
int main() { int result = add(3, 5); cout << "3 + 5 = " << result << endl; // 8 return 0;}和 JS 对比:
- JS:
function add(a, b) { return a + b; } - C++:
int add(int a, int b) { return a + b; }
区别就是 C++ 要写参数和返回值的类型。
无返回值:void
void greet(string name) { cout << "你好," << name << "!" << endl;}void 表示”没有返回值”。
默认参数
int power(int base, int exp = 2) { // exp 默认是 2 int result = 1; for (int i = 0; i < exp; i++) { result *= base; } return result;}
power(5); // 25(默认平方)power(5, 3); // 125(3次方)函数重载:同名不同参数
C++ 允许同名函数,只要参数不同:
int max(int a, int b) { return a > b ? a : b; }double max(double a, double b) { return a > b ? a : b; }
max(3, 5); // 用 int 版本max(3.5, 2.2); // 用 double 版本编译器会根据传参类型自动选对应的函数。
九、数组:装一堆同类型数据
#include <iostream>using namespace std;
int main() { // 声明并初始化数组 int scores[5] = {90, 85, 78, 92, 88};
// 访问(下标从 0 开始) cout << "第一个成绩:" << scores[0] << endl; // 90
// 修改 scores[2] = 80;
// 遍历 for (int i = 0; i < 5; i++) { cout << scores[i] << " "; } cout << endl; // 90 85 80 92 88
return 0;}数组的特点:
- 下标从 0 开始(
scores[0]是第一个) - 长度固定,声明时定死(
int scores[5]就是 5 个) - 所有元素类型相同
求数组长度
int scores[] = {90, 85, 78};int len = sizeof(scores) / sizeof(scores[0]);cout << len << endl; // 3sizeof(scores) 是数组占的总字节数,除以单个元素字节数就是个数。
字符串(字符数组)
C 语言里没有 string,用字符数组;C++ 有 string 类型更方便:
#include <iostream>#include <string>using namespace std;
int main() { string name = "小明"; cout << "长度:" << name.length() << endl; // 2 cout << "拼接:" << name + "你好" << endl; // 小明你好 cout << "取字符:" << name[0] << endl; // 小 return 0;}十、指针:C/C++ 最难也最核心的概念
指针(pointer)就是”存放地址的变量”。
回想之前 Go 教程里讲的快递柜比喻:每个柜子有编号(地址),包裹(数据)放在柜子里。指针就是”柜子编号”,通过编号能打开柜子。
#include <iostream>using namespace std;
int main() { int age = 18;
int* p = &age; // & 取地址,p 存的是 age 的内存地址 cout << "age 的地址:" << p << endl; // 0x7ffe...(一串十六进制) cout << "p 指向的值:" << *p << endl; // 18(* 取值)
*p = 20; // 通过指针修改 age cout << "age 现在:" << age << endl; // 20
return 0;}三个符号记清楚:
| 符号 | 含义 |
|---|---|
& | 取地址(在变量前) |
* | 声明指针类型 / 取值(解引用) |
p | 指针本身(存的是地址) |
为什么需要指针?
场景一:函数修改外部变量。
和 Go 一样,函数参数默认是”值传递”——复制一份进去,函数里改的是副本:
void change(int x) { x = 100; // 改的是副本}
int main() { int n = 5; change(n); cout << n << endl; // 5(没变) return 0;}想真正改外部变量,传地址(指针):
void change(int* x) { *x = 100; // 通过地址改原变量}
int main() { int n = 5; change(&n); // 传 n 的地址 cout << n << endl; // 100(变了!) return 0;}场景二:数组传参。
数组名本身就是指向第一个元素的指针:
void printArray(int arr[], int size) { for (int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl;}
int main() { int nums[] = {1, 2, 3, 4, 5}; printArray(nums, 5); // 1 2 3 4 5 return 0;}初学阶段: 看到 * 和 & 别慌,记住”& 取地址、* 通过地址取值”就行。用得多了自然就熟。
十一、面向对象:类(class)
C++ 相比 C 最大的增强就是面向对象——用”类”把数据和操作绑在一起。
#include <iostream>#include <string>using namespace std;
// 定义一个"学生"类class Student {private: // 私有:外部不能直接访问 string name; int age;
public: // 公有:外部可以调用 // 构造函数:创建对象时自动调用 Student(string n, int a) { name = n; age = a; }
// 方法 void introduce() { cout << "我叫" << name << ",今年" << age << "岁" << endl; }
// 获取私有属性 int getAge() { return age; }};
int main() { // 创建对象 Student s1("小明", 18); Student s2("小红", 17);
s1.introduce(); // 我叫小明,今年18岁 s2.introduce(); // 我叫小红,今年17岁
cout << "小明的年龄:" << s1.getAge() << endl; // 18
return 0;}和之前学的对比:
- JS 的 class、Go 的 struct、C++ 的 class,核心思想都一样——把数据和操作封装在一起
- C++ 多了
public/private访问控制(Go 用大小写区分,C++ 用关键字)
三大特性:封装、继承、多态
继承(Inheritance): 子类复用父类
class Animal {public: void eat() { cout << "吃东西" << endl; }};
class Dog : public Animal { // Dog 继承 Animalpublic: void bark() { cout << "汪汪!" << endl; }};
int main() { Dog d; d.eat(); // 继承来的方法 d.bark(); // 自己的方法 return 0;}多态(Polymorphism): 同一接口,不同行为(用虚函数实现)
class Animal {public: virtual void speak() { // virtual:虚函数 cout << "动物叫" << endl; }};
class Dog : public Animal {public: void speak() override { // override:覆盖父类方法 cout << "汪汪!" << endl; }};
int main() { Animal* a = new Dog(); // 父类指针指向子类对象 a->speak(); // 汪汪!(动态调用子类方法) return 0;}初学阶段先理解”继承是父子关系”,多态等用到了再深入。
十二、几个实用的标准库工具
向量 vector:动态数组(推荐用这个)
用 C++ 建议用 vector 代替裸数组,它长度可以自动增长:
#include <iostream>#include <vector>using namespace std;
int main() { vector<int> nums; // 空向量
nums.push_back(10); // 尾部加元素 nums.push_back(20); nums.push_back(30);
cout << "大小:" << nums.size() << endl; // 3 cout << "第一个:" << nums[0] << endl; // 10
// 遍历 for (int n : nums) { // 范围 for,很简洁 cout << n << " "; } cout << endl; // 10 20 30
return 0;}字符串处理
#include <iostream>#include <string>using namespace std;
int main() { string s = "Hello World";
cout << "长度:" << s.length() << endl; // 11 cout << "查找:" << s.find("World") << endl; // 6(位置)
if (s.find("World") != string::npos) { cout << "包含 World" << endl; }
cout << "子串:" << s.substr(0, 5) << endl; // Hello
return 0;}排序
#include <iostream>#include <vector>#include <algorithm> // 排序需要这个头文件using namespace std;
int main() { vector<int> nums = {5, 2, 8, 1, 9};
sort(nums.begin(), nums.end()); // 升序排序 for (int n : nums) cout << n << " "; cout << endl; // 1 2 5 8 9
return 0;}十三、实战:写一个”猜数字”小游戏
把学到的都用上,写一个完整程序:
#include <iostream>#include <cstdlib> // rand 随机数#include <ctime> // time 时间using namespace std;
int main() { // 用当前时间作为随机种子,这样每次运行数字不同 srand(time(0)); int secret = rand() % 100 + 1; // 生成 1~100 的随机数
int guess; int attempts = 0;
cout << "🎯 猜数字游戏!我在 1~100 里想了一个数,你来猜。" << endl;
while (true) { cout << "请输入你的猜测:"; cin >> guess; attempts++;
if (guess > secret) { cout << "太大了!" << endl; } else if (guess < secret) { cout << "太小了!" << endl; } else { cout << "🎉 猜对了!答案是" << secret << ",你用了" << attempts << "次。" << endl; break; } }
return 0;}编译运行:
g++ guess.cpp -o guess./guess这个程序用到了: 变量、cin 输入、while 循环、if 判断、break、随机数、字符串拼接。把它的每一行都读懂,你的 C++ 基础就扎实了。
练习: 加一个”最多猜 7 次,超了提示失败”的规则。
十四、C 和 C++ 的区别(快速过一遍)
既然标题是 C/C++,顺便说下两者区别:
| 对比 | C | C++ |
|---|---|---|
| 面向对象 | 没有 | 有 class |
| 字符串 | 字符数组(麻烦) | string 类型(方便) |
| 动态数组 | 手动 malloc/free | vector(自动管理) |
| 输入输出 | printf / scanf | cout / cin |
| 文件后缀 | .c | .cpp |
| 编译 | gcc | g++ |
初学建议: 直接学 C++。因为 C++ 包含 C 的几乎所有内容,而且 string、vector 这些工具能让入门舒服很多。等 C++ 熟了,想学 C 就是”减法”。
十五、总结
这一篇我们从零学会了 C/C++:
- C 和 C++ 是什么:C 是祖师爷,C++ 加了面向对象,两者都很底层很快
- 安装环境:g++ 编译器
- Hello World:编译(g++)和运行(./hello)
- 变量和类型:int、double、string、bool,必须写类型
- 输入输出:cout 输出、cin 输入
- 条件循环:if/else、switch、for、while
- 函数:返回类型、void、重载
- 数组:下标从 0 开始,vector 更推荐
- 指针:
&取地址、*取值,函数改外部变量 - 面向对象:class、封装、继承、多态
- 标准库:vector、string、sort
- 实战:猜数字小游戏
C/C++ 是理解”计算机原理”的钥匙。 学完它,你回头看 JavaScript、Go,会发现它们很多设计(比如垃圾回收自动管理内存)都是在帮你省去 C/C++ 里那些要手动处理的事。
下一步: 多写几个小项目(计算器、成绩管理系统、通讯录),把指针和类练熟,你就真正入门 C++ 了。