C
This commit is contained in:
294
C/Ccompile.md
Normal file
294
C/Ccompile.md
Normal file
@@ -0,0 +1,294 @@
|
||||
好,这个问题问得**非常本质**,而且一看就是你已经开始从“会写代码”往“懂工具链 / 懂底层”走了 👍
|
||||
我分三层给你捋清楚:**编译器有哪些 → 编译/汇编/链接的指令 → C 与 C++ 在编译层面的真实差异**。
|
||||
|
||||
---
|
||||
|
||||
## 一、主流 C / C++ 编译器版图(你必须认识的)
|
||||
|
||||
### 1️⃣ GCC / G++
|
||||
|
||||
* **全名**:GNU Compiler Collection
|
||||
* **支持语言**:C / C++ / Fortran / Go / Obj-C / …
|
||||
* **命令**:
|
||||
|
||||
* `gcc` → 主要用来编 C
|
||||
* `g++` → 主要用来编 C++
|
||||
* **平台**:Linux / WSL / macOS / *nix
|
||||
* **特点**:
|
||||
|
||||
* 工业级事实标准
|
||||
* 参数多、控制力极强
|
||||
* 对 ABI、链接、底层非常“真实”
|
||||
|
||||
📌 **重点**:
|
||||
`gcc` 和 `g++` **底层是同一个编译器**,区别在:
|
||||
|
||||
* 默认语言不同
|
||||
* 是否自动链接 `libstdc++`
|
||||
* 是否启用 C++ 语义(name mangling、异常等)
|
||||
|
||||
---
|
||||
|
||||
### 2️⃣ Clang / Clang++
|
||||
|
||||
* **LLVM 系列**
|
||||
* **命令**:
|
||||
|
||||
* `clang`
|
||||
* `clang++`
|
||||
* **平台**:Linux / macOS / Windows
|
||||
* **特点**:
|
||||
|
||||
* 错误提示极其友好(新手 + 老手都爱)
|
||||
* 编译速度快
|
||||
* AST、静态分析能力强
|
||||
|
||||
📌 **现实情况**:
|
||||
|
||||
* macOS 上的 `gcc` 实际就是 `clang`
|
||||
* 现代 C++ 项目大量使用 clang
|
||||
|
||||
---
|
||||
|
||||
### 3️⃣ MSVC(Windows 专属)
|
||||
|
||||
* **微软官方编译器**
|
||||
* **命令**:
|
||||
|
||||
* `cl.exe`
|
||||
* **特点**:
|
||||
|
||||
* Windows ABI 官方实现
|
||||
* C++ 标准支持偏慢但稳定
|
||||
* 和 Visual Studio 深度绑定
|
||||
|
||||
📌 **注意**:
|
||||
|
||||
* MSVC ≠ GCC / Clang
|
||||
* 一些 GCC 的参数 **在 MSVC 上完全不存在**
|
||||
|
||||
---
|
||||
|
||||
### 4️⃣ 其他你只需“知道存在”的
|
||||
|
||||
| 编译器 | 用途 |
|
||||
| --------------- | -------------- |
|
||||
| TinyCC (tcc) | 极快、教学 |
|
||||
| Intel ICC / ICX | 性能优化 |
|
||||
| ARM GCC | 嵌入式 |
|
||||
| MinGW | Windows 上的 GCC |
|
||||
|
||||
---
|
||||
|
||||
## 二、C / C++ 编译的**完整流程**(不是一句 gcc)
|
||||
|
||||
### 🧠 真相:**编译 = 4 个阶段**
|
||||
|
||||
```text
|
||||
源代码
|
||||
↓
|
||||
预处理(cpp)
|
||||
↓
|
||||
编译(cc1 / clang)
|
||||
↓
|
||||
汇编(as)
|
||||
↓
|
||||
链接(ld)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、你问的重点①:**“各种指令”是哪些?**
|
||||
|
||||
### 1️⃣ 预处理指令(只和文本有关)
|
||||
|
||||
```bash
|
||||
gcc -E a.c
|
||||
```
|
||||
|
||||
| 指令 | 作用 |
|
||||
| ---------------- | ---- |
|
||||
| `#include` | 文本展开 |
|
||||
| `#define` | 宏替换 |
|
||||
| `#ifdef` / `#if` | 条件编译 |
|
||||
|
||||
📌 **关键点**:
|
||||
|
||||
* C 和 C++ **完全一样**
|
||||
* 预处理器不知道“类型”“函数”“类”
|
||||
|
||||
---
|
||||
|
||||
### 2️⃣ 编译阶段指令(最核心)
|
||||
|
||||
#### 基础用法
|
||||
|
||||
```bash
|
||||
gcc -c a.c # 只编译,不链接
|
||||
g++ -c a.cpp
|
||||
```
|
||||
|
||||
#### 常用编译参数
|
||||
|
||||
| 参数 | 含义 |
|
||||
| -------------------------------- | ---- |
|
||||
| `-std=c11 / c17 / c++17 / c++20` | 标准 |
|
||||
| `-Wall -Wextra` | 警告 |
|
||||
| `-O0 -O2 -O3` | 优化 |
|
||||
| `-g` | 调试信息 |
|
||||
| `-fno-omit-frame-pointer` | 调试友好 |
|
||||
| `-fsanitize=address` | ASan |
|
||||
|
||||
📌 **重点差异**:
|
||||
|
||||
* C++ 会启用:
|
||||
|
||||
* **函数重载**
|
||||
* **模板实例化**
|
||||
* **名字修饰(name mangling)**
|
||||
|
||||
---
|
||||
|
||||
### 3️⃣ 汇编层(你开始接触底层时很重要)
|
||||
|
||||
```bash
|
||||
gcc -S a.c
|
||||
g++ -S a.cpp
|
||||
```
|
||||
|
||||
📌 差异点:
|
||||
|
||||
* C++ 生成的汇编:
|
||||
|
||||
* 函数名会被改写(`_Z3addii`)
|
||||
* 有构造 / 析构 / 异常展开
|
||||
* C:
|
||||
|
||||
* 函数名基本原样
|
||||
|
||||
---
|
||||
|
||||
### 4️⃣ 链接阶段(很多“玄学错误”的源头)
|
||||
|
||||
```bash
|
||||
gcc a.o b.o -o app
|
||||
g++ a.o b.o -o app
|
||||
```
|
||||
|
||||
#### **最重要的差异**
|
||||
|
||||
| 行为 | gcc | g++ |
|
||||
| ----------------- | --- | --- |
|
||||
| 自动链接 libstdc++ | ❌ | ✅ |
|
||||
| 支持 new / iostream | ❌ | ✅ |
|
||||
|
||||
📌 经典坑:
|
||||
|
||||
```bash
|
||||
gcc main.cpp
|
||||
# undefined reference to std::cout
|
||||
```
|
||||
|
||||
因为 **gcc 不自动链接 C++ 标准库**
|
||||
|
||||
---
|
||||
|
||||
## 四、你问的重点②:**C 与 C++ 在“编译器层面”的差异**
|
||||
|
||||
### 1️⃣ 语言前端不同
|
||||
|
||||
| 项目 | C | C++ |
|
||||
| ---- | -- | --- |
|
||||
| 类型系统 | 简单 | 极复杂 |
|
||||
| 模板 | ❌ | ✅ |
|
||||
| 函数重载 | ❌ | ✅ |
|
||||
| 名字修饰 | ❌ | ✅ |
|
||||
|
||||
📌 本质:
|
||||
|
||||
> **同一个编译器,不同“语言前端”**
|
||||
|
||||
---
|
||||
|
||||
### 2️⃣ Name Mangling(超级重要)
|
||||
|
||||
```cpp
|
||||
int add(int a, int b);
|
||||
```
|
||||
|
||||
| 语言 | 符号名 |
|
||||
| --- | ---------- |
|
||||
| C | `add` |
|
||||
| C++ | `_Z3addii` |
|
||||
|
||||
所以你见过:
|
||||
|
||||
```cpp
|
||||
extern "C" {
|
||||
void foo();
|
||||
}
|
||||
```
|
||||
|
||||
👉 **是为了让 C++ 用 C 的符号规则**
|
||||
|
||||
---
|
||||
|
||||
### 3️⃣ 运行时支持完全不同
|
||||
|
||||
| 项目 | C | C++ |
|
||||
| ----- | ---- | --------- |
|
||||
| 构造/析构 | ❌ | ✅ |
|
||||
| RTTI | ❌ | ✅ |
|
||||
| 异常 | ❌ | ✅ |
|
||||
| 标准库 | libc | libstdc++ |
|
||||
|
||||
📌 所以:
|
||||
|
||||
* C 程序 = **非常薄**
|
||||
* C++ 程序 = **编译器 + 运行时体系**
|
||||
|
||||
---
|
||||
|
||||
### 4️⃣ ABI 差异(工程级别)
|
||||
|
||||
* C ABI:**几乎永远稳定**
|
||||
* C++ ABI:
|
||||
|
||||
* 不同编译器、不同版本可能不兼容
|
||||
* 这就是为什么库常用 **C 接口**
|
||||
|
||||
---
|
||||
|
||||
## 五、给你一个“认知升级总结”
|
||||
|
||||
> 🔥 **C 是“能跑就行的语言”**
|
||||
> 🔥 **C++ 是“需要编译器深度参与的语言”**
|
||||
|
||||
所以你会发现:
|
||||
|
||||
* 学 C → 多学 **内存、指针、汇编**
|
||||
* 学 C++ → 多学 **编译模型、ABI、链接、对象模型**
|
||||
|
||||
---
|
||||
|
||||
## 六、下一步我可以怎么继续帮你?
|
||||
|
||||
你现在这个问题,**已经明显在向系统级程序员靠拢了**。
|
||||
我可以继续给你:
|
||||
|
||||
1️⃣ 用 **同一段代码** 对比
|
||||
|
||||
* gcc / g++ / clang / msvc
|
||||
* 汇编输出差异
|
||||
|
||||
2️⃣ 系统讲一遍
|
||||
|
||||
* **C++ 对象在内存里的真实布局**
|
||||
* vtable / 构造顺序 / 析构顺序
|
||||
|
||||
3️⃣ 专门讲
|
||||
|
||||
* **链接错误为什么那么玄学**
|
||||
* undefined reference 背后的逻辑
|
||||
|
||||
你选一个,我直接给你干到“明白为止”。
|
||||
Reference in New Issue
Block a user