📄 一句话概括
#include 是预处理指令:它在编译之前动手,把指定的文件原样插入到这条指令所在的位置——相当于"借工具"。三个要点:# 开头、独占一行、末尾不带分号;< > 去系统标准库里找," " 先在自己工程目录找;它习惯放在文件最前面,因为后面的代码要用它借来的东西。
一、#include 到底做了什么
很多人以为 #include 是"打开文件"——不完全对。准确说法:
在正式翻译(编译)之前,先把那个文件的内容,一字不差地"贴"到这条指令的位置上。
你写的: #include <iostream>
cout << "hi";
预处理之后变成: (iostream 里的上千行代码贴在这里……)
cout << "hi";
这个"贴"的动作叫预处理,干这活的是预处理器,它在编译器正式开工之前跑一遍。所以:
- 你的
.cpp文件从头到尾只是一份"半成品",预处理器先把它"加工"成完整代码,编译器才接手 - 它不检查语法、也不算数,就是照单搬运
- 这也解释了为什么它末尾不写分号——它不是"语句",是"给预处理器的命令"
📝 生活比喻
写代码像照着菜谱做菜。#include 就是菜谱开头的"备料清单":先把 iostream 这袋调料整袋倒进台面,后面炒菜时直接抓就行。清单不用加句号,也没人管你倒调料的顺序。
二、两种写法:< > 和 " "
| 写法 | 去哪里找 | 用来引入什么 | 例子 |
|---|---|---|---|
#include <文件名> |
系统标准库目录 | 编译器/标准库自带的头文件 | <iostream> <cmath> <iomanip> |
#include "文件名" |
先当前工程目录,找不到再去系统库 | 自己或同事写的头文件 | "myfunc.h" |
记忆:尖括号=进"公家仓库";双引号=先翻"自己抽屉"。现在你只会用到尖括号那种;等到第 9 章之后自己写函数、拆文件时,双引号就会用上了。
三、常打交道的几个标准头文件
| 头文件 | 借来什么 | 什么时候用 |
|---|---|---|
<iostream> |
cin cout cerr(输入输出流) |
几乎每个程序都要 |
<cstdlib> |
system()、随机数等 |
用 system("pause") 时 |
<cmath> |
sqrt pow sin 等数学函数 |
做数学计算时 |
<iomanip> |
setw setprecision 等格式控制 |
排版输出时(2.5.3) |
<string> |
string 字符串类型 |
用 string 存文字时 |
<ctime> |
日期时间函数 | 要取当前时间时 |
写法提醒:一个文件可以写多条 #include,一般一行一条,按"标准库在前、自己的在后"排。
四、动手 Demo:两次"故意犯病",看报错长什么样
拿 2.1 的 hello2.cpp,做两轮实验(每轮改完 Ctrl+S → F11,记下报错原话):
第一轮:把 iostream 拼错
#include <iostrem> // 少写一个 a
- 预期:报错类似
iostrem: No such file or directory——预处理阶段就拦住了,编译器根本没开始翻译 - 结论:
#include的错误属于"找不到文件",措辞和语法错误完全不同
第二轮:把 #include 整行注释掉
// #include <iostream>
- 预期:报错类似
'cout' was not declared in this scope——编译器不认识cout是谁 - 结论:工具没借来,后面的活儿就干不了。这两条报错合起来记:文件找不到 → 查拼写;名字不认识 → 查头文件
看到什么算成功:两次都能说出"错在哪一步"(第一次错在预处理,第二次错在编译)。
30 秒实验:再故意加一句 #include <iostream>;(末尾多写一个分号),编译看看——多数编译器会通过(预处理器把分号当成多余字符忽略掉),但这不合规范。体会一下:"能跑"不等于"写对"。
五、常见误区
- "
#include要加分号"——不用。它是预处理指令,行末不加分号;加了通常不报错,但属于坏习惯 - "把
iostream写成iostream.h也一样"——不一样。.h是 C 语言时代的老写法(如<stdio.h>),C++ 标准库不带.h(<cstdio>是 C 兼容版)。写错通常直接报"找不到文件" - "头文件可以随便放位置"——放在最前面。它借来的名字要先出现,后面才能用;放到
main后面就会报"未声明" - "
#include会把整个标准库都塞进程序、让程序变慢"——不会。它只影响编译阶段,最终程序里只会留下真正用到的部分(第 1 章说的"零开销")