← 开始学习

FIRST PROGRAM / MACOS + C++20

把一个 .cpp 文件,
编译成能运行的程序。

从打开终端开始,亲手完成保存、编译、运行和重新编译。主线按 Mac 编写;Linux 的编译命令相同,工具安装方式按系统处理。

第一次约 20–30 分钟,计入首个基础单元的动手时间。还不需要 CMake、LLVM IR 或加速卡;手机可以阅读,实际输入命令需要电脑终端。

已有 first.cpp?最短操作是这两步

本页的四个编译诊断选项已统一到新04的选项说明;第一次使用这些选项,先读该小节,再回到本页操作。

先在终端进入 first.cpp 所在目录,再输入下面这行。文件若叫 main.cpp,把输入名换成它即可。

在源码所在目录执行
clang++ -std=c++20 -Wall -Wextra first.cpp -o first && ./first

first.cpp 是输入源码;-o first 把输出程序命名为 first./first 表示运行当前目录中的这个程序;&& 表示前面的编译成功后才运行。

1. 打开终端,确认编译器

  1. 在 Mac 按 Command + 空格,搜索 Terminal / 终端并打开。
  2. 看到可输入文字的提示符后,输入下面命令并按回车。网页中的命令写在终端,不写进 C++ 文件;也不用复制提示符 $% 或包住代码的三反引号。
clang++ --version

能看到 Clang 的版本文字就继续。版本号不需要与教材机器完全一致,但必须支持 C++20。本教程的编译操作已用 Apple Clang 17 在 Mac 上执行。

Mac 没有编译器,怎样准备?

输入下面命令,按系统弹窗完成 Command Line Tools 安装。下载完成后重新运行 clang++ --version,能显示版本再继续;等待安装的时间另计。已有工具时不必重复安装,也不用先下载完整 Xcode。

xcode-select --install

这是供你在需要时操作的安装入口;编写本教程时使用已有工具,没有重新安装或更改系统。

Linux 或 Windows 怎么办?

Linux 已有支持 C++20 的 Clang 时,下面命令同样适用;没有时按发行版的官方软件包说明安装 Clang。已有 GCC 时,可把示例的 clang++ 换成支持 C++20 的 g++,仍需实际检查输出。本轮只验证了 Mac/Clang 路径。

Windows 的 PowerShell/MSVC 使用不同的工具与运行写法;已有 WSL 环境可按 Linux 路径操作。不要直接把 macOS 的安装命令粘贴到 Windows。

2. 创建目录,把代码保存为 first.cpp

在终端逐行输入,每行回车:

mkdir -p "$HOME/cpp-practice"
cd "$HOME/cpp-practice"
pwd

mkdir -p 创建练习目录(已存在则继续使用);cd 切换终端的当前目录;pwd 显示当前位置。$HOME 是你的个人主目录。路径有空格时要加引号,例如 cd "$HOME/My Cpp Practice"。进入目录只改变终端位置,不会移动文件。

先运行 ls 检查目录。若已经有 first.cppfirst,保留旧练习,先创建并进入一个新的练习目录,例如 cpp-practice-2;后续所有 cd 都使用你实际选择的路径。源码与程序仍统一命名为 first.cppfirst。接着打开终端编辑器:

nano first.cpp

把下面这段完整程序输入或粘贴进去。不要覆盖以前练习的内容。

first.cpp · 与第 01 章共用同一源码
#include <iostream>
int main() {
    int count{2};
    count = count + 1;
    std::cout << count << '\n';
    return 0;
}
  1. Control + O(字母 O)保存,再按回车确认文件名。
  2. Control + X 退出编辑器,回到终端。这里用的是 Control,不是 Command。
  3. 输入 ls;文件列表应包含 first.cpp。只复制代码到剪贴板,还不等于保存了文件。

若用已有的图形编辑器,保存为这个目录里的纯文本 first.cpp。避免 first.cpp.txt、富文本和弯引号。没有 nano 时也可用这种方式。

下载同一份 first.cpp →

3. 编译,然后运行

先生成程序

从这个小节直接开始时,先读命令中编译诊断选项的用途,再执行:

clang++ -std=c++20 -Wall -Wextra first.cpp -o first

编译成功通常没有输出,只会回到提示符。输入 ls,现在应能看到源码 first.cpp 和程序 first。出现 error 时先修正,不继续运行目录里可能残留的旧程序。

这一段意思
clang++调用 C++ 编译驱动;这条命令会完成编译和链接。
-std=c++20使用 C++20 语言标准。
-Wall -Wextra用途见本节命令前的选项说明入口。
first.cpp要读取的源文件,必须与实际保存的名字一致。
-o first指定输出文件名;是字母 o,不是数字 0。

再启动程序

先预测 2 + 1 会输出什么,再输入:

./first

终端应显示:

3

. 表示当前目录,所以 ./first 明确指出程序的位置。单独输入 first,终端通常只会到 PATH 中找命令;输入 ./first.cpp 也不会编译 C++。

没有写 -o、或者想看退出码呢?

Clang 在这里省略 -o 通常会生成 a.out,对应运行 ./a.out。使用明确名字更容易找到程序。

运行结束后紧接着输入 echo $?,显示的是刚才命令的退出码。这里应为 0,来自 return 0;;输出的数字 3 与退出码 0 是两件事。不要在检查退出码前先执行别的命令。

观察 · 推演

改源码、编译、运行,是三个不同动作

first.cpp · 源码count 初值 2first · 可执行程序尚未生成01 / 05 · PIPELINEfirst.cpp · 源码count 初值 2first · 可执行程序尚未生成01 / 05 · PIPELINE
1. 保存源码

编辑器把文字保存到 first.cpp;此时还没有生成程序。

1 / 5
阅读完整推演文字
  1. 1. 保存源码

    first.cpp · 源码:count 初值 2;first · 可执行程序:尚未生成

    编辑器把文字保存到 first.cpp;此时还没有生成程序。

  2. 2. 编译并链接

    first.cpp:count 初值 2;clang++:编译 + 链接;first:新程序

    clang++ 读取 first.cpp,编译并链接,-o first 指定输出文件名。成功通常没有文字输出。

  3. 3. 运行程序

    ./first:启动程序;终端输出:3

    ./first 启动当前目录的程序;它执行加一并输出 3。运行时不会重新读取 C++ 源码。

  4. 4. 只改源码,程序没有更新

    first.cpp:初值已改为 5;first:仍是旧程序;./first 输出:仍为 3

    将 first.cpp 的初值改为 5 并保存。若没有重新编译,./first 仍运行旧程序,输出 3。

  5. 5. 重新编译,再运行

    first.cpp:初值 5;重新编译:生成新 first;./first 输出:6

    再次执行编译命令,成功后运行,新程序才输出 6。&& 可以阻止编译失败后继续运行旧程序。

4. 改一行,亲眼看见“重新编译”

  1. 再次执行 nano first.cpp,把 int count{2}; 改成 int count{5};,保存并退出。
  2. 先直接执行 ./first。它仍应输出 3:你只改了源码,旧程序还在。
  3. 再执行下面这行,编译成功后会运行新程序:
日常使用:编译成功才运行
clang++ -std=c++20 -Wall -Wextra first.cpp -o first && ./first

这次应输出 6。以后每次改完代码,先保存,再重新编译;网页的“复制代码”按钮只复制文字。

5. 下载的源码怎么运行?

下载第01章的 copy.cpp →

点击下载后,先确认浏览器把文件存到了哪里。若位于 Downloads 目录,可以执行:

cd "$HOME/Downloads"
ls

确认列表里有 copy.cpp。浏览器若存成 copy (1).cpp,在自己的练习副本中改成便于输入的名字,或在命令中给完整文件名加引号。

运行实际下载的文件
clang++ -std=c++20 copy.cpp -o copy && ./copy

这里输入名是 copy.cpp,输出名是 copy,所以运行 ./copy。先预测,再对照第01章的复制与状态例子。其他单文件示例使用对应下载文件;多文件程序与厂商 SDK 按所属章节的完整命令运行。

6. 报错先从哪一条看?

no such file or directory / no input files

终端没有找到你写在命令中的源码。

先运行 pwd 和 ls;检查当前目录、大小写及 first.cpp 是否误存为 first.cpp.txt。不要把示例名当作自己实际的文件名。

command not found: clang++ / developer tools 提示

编译器未准备好,或命令写错。

macOS 按下方工具准备步骤检查;Linux 核对自己的 Clang 安装。不要把 g++、clang 和 clang++ 的名字随意混用。

expected ';' / use of undeclared identifier

C++ 源码有语法或名字错误。

先看第一条 error 的文件名、行号、列号;核对上一行的分号和变量拼写。修正、保存后重新编译。后续错误可能只是第一条引起的。

Undefined symbols / undefined reference / missing main

链接阶段找不到需要的定义。

确认文件有 int main(),且不是从函数中间开始复制的片段。多文件程序要一起编译实际需要的 .cpp;不能只把头文件当完整实现。

./first: no such file or directory / permission denied

没有可运行的该文件,或正在尝试运行源码。

先检查编译是否成功、-o 后的名字及当前目录。运行 ./first;first.cpp 是文字,不要用 chmod 来把它“变成程序”。

修改后输出没有变化

运行了旧程序,或改的是另一个目录的文件。

保存编辑器内容,用 pwd、ls 确认位置,重新编译;随后运行与 -o 名字一致的程序。使用本页的 && 命令连接。

需要求助时,提供实际文件名、pwd、编译命令、第一条完整错误和附近几行源码;不要只提供最后一句“编译失败”。

完成后再回到 C++ 内容

现在应能独立做到:找到源文件、编译出指定名字的程序、运行它、修改后重新编译,并解释 3 为什么变成 6。编译成功只说明构建完成,程序是否正确还要对照输入和预期。

后面学调试时用的两种构建

如果刚才去了 Downloads,先切回 first.cpp 所在目录。下面以默认练习目录为例;若前面用了新目录名,把路径一起换成自己的。

Debug:保留调试信息

cd "$HOME/cpp-practice" && clang++ -std=c++20 -Wall -Wextra -g -O0 first.cpp -o first-debug && ./first-debug

-g 生成调试信息,-O0 关闭优化;后面的 LLDB 课程会使用。

ASan / UBSan:运行时检查

cd "$HOME/cpp-practice" && clang++ -std=c++20 -g -O1 -fsanitize=address,undefined -fno-omit-frame-pointer first.cpp -o first-sanitize && ./first-sanitize

这些动态检查只覆盖实际执行的路径,不能替代测试。没有报错时,程序仍输出它自己的结果。

多文件构建、头文件与链接见 第17章;LLVM IR 和汇编放到后面的 编译器实验

资料与验证范围

本页源码与第 01 章、下载文件共用同一教学文件;编译、重新编译及故障实验在现有 Mac/Clang 上检查。工具安装入口、其他操作系统与厂商 SDK 不属于这些运行结果。