2024-10-17 10:56:34 +02:00
# 第一章: CLion 高级配置(⭐)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 1.1 安装和配置 WSL2
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 1.1.1 概述
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* WSL2, 全称为 Windows Subsystem for Linux 2, 是微软提供的一种技术, 允许用户在 Windows 操作系统上运行 Linux 内核。WSL2 是 WSL1 的升级版,它引入了一个真正的 Linux 内核来代替 WSL1 中使用的兼容层,从而提供更高的性能和更广泛的系统调用支持。
* 和传统的虚拟化技术的对比,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/1.svg)
2024-10-08 05:44:30 +02:00
> [!NOTE]
>
2024-10-17 10:56:34 +02:00
> WSL2 的功能,如下所示:
2024-10-08 05:44:30 +02:00
>
2024-10-17 10:56:34 +02:00
> * ① **真实的 Linux 内核**: WSL2 使用了微软开发的轻量级虚拟机,它包含了一个完整的 Linux 内核。这意味着 WSL2 能够运行更多的 Linux 应用程序,并且支持更多的系统调用。
> * ② **文件系统性能提升**: WSL2 的文件系统性能比 WSL1 有显著提升。对于 I/O 密集型的操作, 如: 编译代码或数据库操作, WSL2 能够提供更快的速度。
> * ③ **兼容性增强**:由于使用了真实的 Linux 内核, WSL2 对 Linux 应用程序的兼容性大幅提高。许多在 WSL1 上不能运行或需要调整的应用程序,可以在 WSL2 上直接运行。
> * ④ **网络功能改进**: WSL2 提供了更好的网络集成,能够更容易地与 Windows 上的其他网络资源进行交互。
> * ⑤ **资源使用优化**: WSL2 使用轻量级虚拟机,比传统的虚拟机占用更少的资源,同时提供了类似的隔离和安全性。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
> [!NOTE]
2024-10-17 03:20:50 +02:00
>
2024-10-17 10:56:34 +02:00
> WSL2 的用途,如下所示:
2024-10-08 05:44:30 +02:00
>
2024-10-17 10:56:34 +02:00
> * ① **开发环境**: WSL2 为开发者提供了一个原生的 Linux 开发环境,而无需离开 Windows 。这对于需要在 Linux 上开发、测试或运行应用程序的开发者非常有帮助。
> * ② **学习和实验**:用户可以使用 WSL2 在 Windows 上学习和实验 Linux 命令行工具和应用程序,而无需设置双重引导系统或安装虚拟机。
> * ③ **多平台开发**: 对于跨平台开发者来说, WSL2 允许他们在一个操作系统上同时进行 Windows 和 Linux 平台的开发和测试,提高工作效率。
> * ④ **运行 Linux 工具和应用程序**: WSL2 支持在 Windows 上直接运行各种 Linux 工具和应用程序, 如: Docker、数据库、编程语言环境等。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 1.1.2 WSL2 的安装
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ① BIOS 或 UEFI 中,开启虚拟化:步骤略。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/2.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ② 查看是否开启了虚拟化:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/3.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ③ 启用适用于 Linux 的 Windows 子系统:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
> [!IMPORTANT]
>
> 以管理员身份打开 PowerShell 并运行,执行完下面命令之后,如果提示需要重启计算机,那就重启计算机!!!
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```powershell
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
![](./assets/4.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ④ 启用虚拟机功能:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
> [!IMPORTANT]
>
> 以管理员身份打开 PowerShell 并运行,执行完下面命令之后,如果提示需要重启计算机,那就重启计算机!!!
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```powershell
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
![](./assets/5.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ⑤ 更新 Linux 内核包:
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
> [!IMPORTANT]
2024-10-17 03:20:50 +02:00
>
2024-10-17 10:56:34 +02:00
> WSL2 的最新 Linux 内核包托管在 GitHub 上,某些国家可能会污染 Github 相关的域名,那么就需要手动下载,然后安装即可,下载地址在[这里](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi)。
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
```powershell
wsl --update
```
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/6.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ⑥ 将 wsl2 设置为默认版本:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```powershell
wsl --set-default-version 2
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
![](./assets/7.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ⑦ 查看官方在线支持的 Linux 版本:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```powershell
wsl --list --online
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/8.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ⑧ 安装指定版本的 Linux :
2024-10-08 05:44:30 +02:00
2024-10-17 03:20:50 +02:00
> [!IMPORTANT]
>
2024-10-17 10:56:34 +02:00
> 官方支持的 Linux 版本,托管在 Github 上,某些国家可能会污染 Github 的域名,有如下两种解决方案:
>
> * ① 科学上网。
> * ② 在 `Microsoft Store` 中搜索并安装。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```powershell
wsl --install Ubuntu-24.04
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/9.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ⑨ 在 Microsoft Store 中搜索并安装(可选):
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/10.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ⑩ 查询本地安装的 Linux 版本:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```powershell
wsl --list
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/11.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 1.1.3 配置 WSL2
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 本人的安装的是 AlmaLinux9 ,所以需要执行如下命令,以便安装 cmake 相关工具链:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
sudo dnf update -y # 更新包管理器
sudo dnf groupinstall "Development Tools" -y # 安装开发工具包
sudo dnf install gcc gcc-c++ -y # 安装GCC相关工具链
sudo dnf install cmake -y # 安装 cmake
sudo dnf install make -y # 安装 make
sudo dnf install gdb -y # 安装 gdb
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/12.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 可以通过 CLion 测试是否安装成功:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/13.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 1.1.4 配置 WSL2
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 本人的安装的是 Ubuntu 24.04,所以需要执行如下命令,以便安装 cmake 相关工具链:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
sudo apt update & & sudo apt upgrade -y # 更新包管理器
sudo apt install build-essential -y # 安装开发工具包
sudo apt install gcc g++ -y # 安装 GCC 相关工具链
sudo apt install cmake -y # 安装 cmake
sudo apt install gdb -y # 安装 gdb
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/14.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 可以通过 CLion 测试是否安装成功:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/15.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 1.2 切换 CLion 中的 cmake 的工具链
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 可以在 CLoin 中切换 cmake 的工具链,以便支持不同平台的 cmake ,即:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/16.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 1.3 修改 CMakeLists.txt 文件
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 前文也提到了,在一个 C 语言项目中,只能有一个 main() 函数;但是,我们可以修改 `CMakeLists.txt` 文件的内容,以便其支持在一个 C 语言项目中,可以同时运行多个包含 main() 函数的文件。
2024-10-08 05:44:30 +02:00
2024-10-17 03:20:50 +02:00
> [!NOTE]
>
2024-10-17 10:56:34 +02:00
> * ① 其实,这样设置的目的:就是为了让每个 `.c` 文件都可以编译为一个独立的可执行文件,而不是所有的 `.c` 文件编译为一个可执行文件。
> * ② 在实际开发中,对于 C 语言项目而言,当然必须只能有一个 `main()` 函数(只有一个 `.c` 文件包含 `main()` 函数,其余的 `.c` 文件中包含函数声明或函数实现),因为程序有且仅有一个入口。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* `CMakeLists.txt` 文件的位置,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/17.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* `CMakeLists.txt` 文件的内容,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```txt
cmake_minimum_required(VERSION 3.22.1)
# 项目名称和版本号
project(c-study VERSION 1.0 LANGUAGES C)
# 设置 C 标准
set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED True)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-D_DEBUG)
elseif (CMAKE_BUILD_TYPE STREQUAL "Release")
add_definitions(-DNDEBUG)
elseif (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
add_definitions(-DRELWITHDEBINFO)
elseif (CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
add_definitions(-DMINSIZEREL)
endif ()
# 辅助函数,用于递归查找所有源文件
function(collect_sources result dir)
file(GLOB_RECURSE new_sources "${dir}/*.c")
set(${result} ${${result}} ${new_sources} PARENT_SCOPE)
endfunction()
# 查找顶层 include 目录(如果存在)
if (EXISTS "${CMAKE_SOURCE_DIR}/include")
include_directories(${CMAKE_SOURCE_DIR}/include)
endif ()
# 查找所有源文件
set(SOURCES)
collect_sources(SOURCES ${CMAKE_SOURCE_DIR})
# 用于存储已经处理过的可执行文件名,防止重复
set(EXECUTABLE_NAMES)
# 创建可执行文件
foreach (SOURCE ${SOURCES})
# 获取文件的相对路径
file(RELATIVE_PATH REL_PATH ${CMAKE_SOURCE_DIR} ${SOURCE})
# 将路径中的斜杠替换为下划线,生成唯一的可执行文件名
string(REPLACE "/" "_" EXECUTABLE_NAME ${REL_PATH})
string(REPLACE "\\" "_" EXECUTABLE_NAME ${EXECUTABLE_NAME})
string(REPLACE "." "_" EXECUTABLE_NAME ${EXECUTABLE_NAME})
# 处理与 CMakeLists.txt 文件同名的问题
if (${EXECUTABLE_NAME} STREQUAL "CMakeLists_txt")
set(EXECUTABLE_NAME "${EXECUTABLE_NAME}_exec")
endif ()
# 检查是否已经创建过同名的可执行文件
if (NOT EXECUTABLE_NAME IN_LIST EXECUTABLE_NAMES)
list(APPEND EXECUTABLE_NAMES ${EXECUTABLE_NAME})
# 链接 math 库
LINK_LIBRARIES(m)
# 创建可执行文件
add_executable(${EXECUTABLE_NAME} ${SOURCE})
# 查找源文件所在的目录,并添加为包含目录(头文件可能在同一目录下)
get_filename_component(DIR ${SOURCE} DIRECTORY)
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${DIR})
# 检查并添加子目录中的 include 目录(如果存在)
if (EXISTS "${DIR}/include")
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${DIR}/include)
endif ()
# 检查并添加 module 目录中的所有 C 文件(如果存在)
if (EXISTS "${DIR}/module")
file(GLOB_RECURSE MODULE_SOURCES "${DIR}/module/*.c")
target_sources(${EXECUTABLE_NAME} PRIVATE ${MODULE_SOURCES})
endif ()
endif ()
endforeach ()
```
## 1.4 配置 .clang-format 文件
* 配置 `.clang-format` 格式化文件,以便写代码的时候,可以自动保存并格式化 C 程序代码,如下所示:
![](./assets/18.png)
* `.clang-format` 的内容,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```txt
BasedOnStyle: LLVM
IndentWidth: 4
UseTab: Never
ColumnLimit: 0
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
# 控制大括号的位置
BreakBeforeBraces: Attach
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
# 控制空行的使用
EmptyLineBeforeAccessModifier: Never
KeepEmptyLinesAtTheStartOfBlocks: true
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
# 控制短函数、短 if 语句和循环的格式
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
# 控制其他格式选项
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
# 控制注释的格式化
ReflowComments: true
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
# 控制包含指令的格式化
IncludeBlocks: Regroup
SortIncludes: CaseInsensitive
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
SpaceBeforeParens: ControlStatements
SpacesInParentheses: false
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
# 控制 switch-case 格式
IndentCaseLabels: true
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
* CLion 中配置`保存`的时候`自动格式化`,即:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/19.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 1.5 配置 .gitignore 文件
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 需要在项目中,配置 `.gitignore` 文件,以便在提交代码到 Git 仓库的时候,忽略某些文件或目录,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/20.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* `.gitignore` 文件的内容,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 03:20:50 +02:00
```txt
2024-10-17 10:56:34 +02:00
.vscode
.idea
cmake-build-*
build
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
## 1.6 演示
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
* 我们可以在项目中,临时创建或复制一个文件,看上述配置是否生效,即:
2024-10-08 05:44:30 +02:00
2024-10-17 03:20:50 +02:00
> [!NOTE]
>
2024-10-17 10:56:34 +02:00
> 如果是复制并粘贴一个文件到项目中,请点击`重新加载 CMake 项目`! ! !
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/21.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
# 第二章: C 语言的编译过程(⭐)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 2.1 概述
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* C 程序的编译过程,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/22.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 过程 ① :编写(编辑)源代码,即:编写 C 语言源程序代码,并以文件的形式存储在磁盘中。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
> [!NOTE]
2024-10-17 03:20:50 +02:00
>
2024-10-17 10:56:34 +02:00
> 源程序需要以 `.c` 作为扩展名。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 过程 ② :编译,即:将 C 语言源程序转换为`目标程序(或目标文件)`。如果程序没有错误,没有任何提示,就会生成一个扩展名为 `.obj` 或 `.o` 的二进制文件。C 语言中的每条可执行语句经过编译之后,最终都会转换为二进制的机器指令。
2024-10-08 05:44:30 +02:00
2024-10-17 03:20:50 +02:00
> [!NOTE]
>
2024-10-17 10:56:34 +02:00
> * ① 其实,`编译阶段`包含了`预处理`、`编译`和`汇编`。
>
> * ② `预处理`是编译过程的第一个阶段。在这个阶段,预处理器处理源代码中的指令(例如:`#include`、`#define`等),主要任务包括:
>
> * 头文件包含:将头文件的内容插入到源文件中。例如:`#include <stdio.h>`会被替换为`stdio.h`文件的内容。
> * 宏展开:替换宏定义。例如:`#define PI 3.14`会将代码中的`PI`替换为`3.14`。
> * 条件编译:根据条件指令(如:`#ifdef`、`#ifndef`)有选择地编译代码。
>
> * 删除代码中的注释,但是不会进行语法检查。
>
> * 预处理完成后,生成一个扩展名为`.i`的中间文件。
>
> * ③ `编译`是将预处理后的源代码转换为汇编代码的过程。在这个阶段,编译器会检查代码的语法和语义,将其转换为目标机器的汇编语言,生成一个扩展名为`.s`的汇编文件。
>
> * ④ `汇编`是将汇编代码转换为机器代码(也称为目标代码或目标文件)的过程。在这个阶段,汇编器将汇编指令转换为二进制机器指令,生成一个扩展名为`.o`或 `.obj`的目标文件。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 过程 ③ :链接(连接),即:将编译形成的目标文件 `*.obj` 或 `*.o` 和库函数以及其他目录文件`链接`,形成一个统一的二进制文件 `*.exe` 。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
>[!NOTE]
2024-10-17 03:20:50 +02:00
>
2024-10-17 10:56:34 +02:00
>* 为什么需要链接库文件?
>* 因为我们的 C 程序会使用 C 程序库中的内容,如:`< stdio.h > ` 中的 `printf()` 函数,这些函数不是程序员自己写的,而是 C 程序库中提供的, 因此需要链接。其实, 在链接过程中, 还会加入启动代码, 这个启动代码( 和系统相关, Linux 下主要有 crt0.c、crti.c 等,它们设置堆栈后,再调用 main() 函数)负责初始化程序运行时的环境。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 过程 ④ :执行,即:有了可执行的 `*.exe` 文件,我们就可以在控制台上执行运行此 `*.exe` 文件。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
> [!NOTE]
>
> 如果`修改`了源代码,还需要重新`编译`、`链接`,并生成新的 `*.exe`文件,再执行,方能生效。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 2.2 GCC 编译器的介绍
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 编辑器, 如: vim 、vscode 等,是指我们用它来编写源程序的(编辑代码),而我们写的代码语句,电脑是不懂的,我们需要把它转成电脑能懂的语句,编译器就是这样的转化工具。换言之,我们用编辑器编写程序,由编译器编译后才可以运行!
* 编译器是将易于编写、阅读和维护的高级计算机语言翻译为计算机能解读、运行的低级机器语言的程序。
* gcc( GNU Compiler Collection, GNU 编译器套件),是由 GNU 开发的编程语言编译器。gcc 原本作为 GNU 操作系统的官方编译器,现已被大多数类 Unix 操作系统( 如: Linux、BSD、Mac OS X 等) 采纳为标准的编译器, gcc 同样适用于微软的 Windows 。
* gcc 最初用于编译 C 语言,随着项目的发展, gcc 已经成为了能够编译 C、C++、Java、Ada、fortran、Object C、Object C++、Go 语言的编译器大家族。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 2.3 通过 gcc 直接生成可执行文件
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
* 示例:进行预处理、编译、汇编和链接
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
gcc HelloWorld.c -o HelloWorld.exe
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
![](./assets/23.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 2.4 通过 gcc 分步编译
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 2.4.1 概述
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 预处理命令:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
# 通常以 .i 结尾表示这个文件是一个中间状态
gcc -E 源文件.c -o 源文件.i
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 编译(预处理和编译)命令:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
# 在 Linux 中,通常以 .s 结尾;在 Windows 中,通常以 .asm 结尾
gcc -S 源文件.i -o 源文件.s
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 汇编(预处理、编译和汇编)命令:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
# 在 Linux 中,通常以 .o 结尾;在 Windows 中,通常以 .obj 结尾
gcc -c 源文件.s -o 源文件.o
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 链接(预处理、编译、汇编和链接)命令:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
# 在 Linux 中,通常以 .out 结尾;在 Windows 中,通常以 .exe 结尾
gcc 源文件.o -o 源文件.exe
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
### 2.4.2 应用示例
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 示例:只进行预处理
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
gcc -E HelloWorld.c -o HelloWorld.i
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/24.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 示例:只进行预处理和编译
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
gcc -S HelloWorld.i -o HelloWorld.s
```
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/25.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 示例:只进行预处理、编译和汇编
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
gcc -c HelloWorld.s -o HelloWorld.o
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
![](./assets/26.gif)
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
* 示例:进行预处理、编译、汇编和链接
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
gcc HelloWorld.o -o HelloWorld.exe
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/27.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
# 第三章:附录
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 3.1 WSL2 代理问题
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 在安装和配置 WSL2 之后,可能会出现如下的提示,即:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/28.png)
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
* 那么,只需要修改 `%USERPROFILE%\.wslconfig` 文件,内容如下:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
> [!NOTE]
>
> 如果没有该文件,则需要自己新建该文件!!!
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
```txt
[wsl2]
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
[experimental]
# requires dnsTunneling but are also OPTIONAL
bestEffortDnsParsing=true
useWindowsDnsCache=true
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
![](./assets/29.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 在命令行中,执行如下的命令:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
wsl --shutdown
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/30.gif)
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
* 此时,再打开终端,就没有这种提示了:
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/31.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 3.2 CLion 调试问题
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 在 CLion 中进行 run( 运行) 程序的时候, 对于 `printf` 函数或 `scanf` 函数很正常,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/32.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 但是,当我们 debug( 调试) 的时候,对于 `printf` 函数或 `scanf` 函数会一直没有输出,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/33.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 原因是 `scanf` 函数并不是直接让用户从键盘输入数据,而是先检查缓冲区,处理缓冲区中的数据;当遇到 `scanf` 函数时,程序会先检查输入缓冲区中是否有数据,所以解决方案就是`禁用缓冲区`,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```c {5}
2024-10-08 05:44:30 +02:00
#include <stdio.h>
int main() {
2024-10-17 10:56:34 +02:00
// 禁用 stdout 缓冲区
setbuf(stdout, NULL);
2024-10-08 05:44:30 +02:00
2024-10-17 03:20:50 +02:00
int a, b, c;
printf("请输入整数 a 、b 和 c 的值:");
scanf("%d %d %d", & a, & b, &c);
2024-10-08 05:44:30 +02:00
2024-10-17 03:20:50 +02:00
int result = a * b * c;
printf("%d × %d × %d = %d", a, b, c, result);
2024-10-08 05:44:30 +02:00
return 0;
}
```
2024-10-17 10:56:34 +02:00
* 那么,就会达到我们想要的效果了,如下所示:
![](./assets/34.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 3.3 Win 中文乱码问题
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 之前,我们提及到,在 Win 中,如果出现`中文乱码`问题,就需要去`语言和区别`设置`系统区域`的编码为 UTF-8 ; 但是, 这样可能会造成其它的软件出现中文乱码问题, 如: Xshell 等。
2024-10-08 05:44:30 +02:00
> [!NOTE]
>
2024-10-17 10:56:34 +02:00
> * ① 之所以,修改系统的编码为 UTF-8 会出现问题,是因为早期的 Win 系统的中文默认编码是 GBK( 目前也是, Win 并没有强制第三方软件使用 UTF-8 编码) ,而 Xshell 等也使用的这些编码,一旦我们修改为 UTF-8 之后,可能会造成这些第三方软件出现中文乱码问题(第三方软件适配问题,相信将来应该都会切换为 UTF-8 编码),体验较差!!!
> * ② 在 Linux 或 MacOS 之所以不会出现中文乱码的问题,是因为这些系统默认的编码就是 UTF-8 。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 其实,还有一种解决方案,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/35.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/36.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/37.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 测试一下,是否配置成功:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/38.gif)
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
## 3.4 CLion 中自动导入头文件
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 在 CLion 中,最为强大的功能就是直接输入函数,然后让 IDE 帮我们自动导入头文件,包括自定义的头文件,相当实用。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
> [!NOTE]
2024-10-08 05:44:30 +02:00
>
2024-10-17 10:56:34 +02:00
> * ① CLion 中的`自动导入头文件`的`快捷键`是 `Alt + Enter` 。
> * ② CLion 中的`自动提取变量的类型`的`快捷键`是 `Ctrl + Alt + V` 。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/39.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 开启自动导入头文件的步骤,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/40.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/41.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 3.5 WSL2 启用 systemd
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 3.5.1 概述
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 根据 [systemd.io ](https://systemd.io/ ): “systemd 是 Linux 系统的基本构建基块套件。 它提供一个系统和服务管理器,该管理器作为 PID 1 运行并启动系统的其余部分。”
* Systemd 主要是一个 init 系统和服务管理器,它包括按需启动守护程序、装载和自动装载点维护、快照支持以及使用 Linux 控制组进行跟踪等功能。
* 大多数主要的 Linux 发行版现在都运行 systemd, 因此在 WSL2 上启用它可使体验更接近于使用裸机 Linux。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
> [!CAUTION]
2024-10-08 05:44:30 +02:00
>
2024-10-17 10:56:34 +02:00
> * ① 默认情况下,在 WSL2 中,只有 Ubuntu 才会将 systemd 作为 pid-1 的守护进程(微软维护和定制的 Ubuntu 版本,在 GitHub 的 Codespace 中默认的 Linux 环境就是 Ubuntu) 。而其余基于 WSL2 为内核的 Linux 发行版本并不会将 systemd 作为 pid-1 的守护进程,而是会使用 init 作为 pid-1 的守护进程。
> * ② 需要注意的是,很多 Linux 软件都需要 systemd 来进行管理, 如: Docker 。
> * ③ 本次以 AlmaLinux9 作为演示!!!
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 检查进程树,判断 systemd 是否正在运行:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
ps -p 1 -o comm= # 如果显示 systemd ,则表示 systemd 正在运行
2024-10-17 03:20:50 +02:00
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/42.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 3.5.2 操作步骤
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ① 查询 WSL2 的版本,确保 WSL2 的版本为 `0.67.6` 或更高版本:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
# 如果未满足要求,则使用 wsl --update 更新 WSL2 版本
wsl --version # 在 win 中的 cmd 或 PowerShell 执行该命令
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
![](./assets/43.png)
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
* ② 向 `/etc/wsl.conf` 配置文件中写入以下内容:
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
```shell
cat < < EOF | tee / etc / wsl . conf
[boot]
systemd=true
EOF
2024-10-17 03:20:50 +02:00
```
2024-10-17 10:56:34 +02:00
![](./assets/44.gif)
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
* ③ 重启 WSL 实例:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
wsl --shutdown # 在 win 中的 cmd 或 PowerShell 执行该命令
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
![](./assets/45.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ④ 查看是否启用成功:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
ps -p 1 -o comm=
2024-10-17 03:20:50 +02:00
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/46.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 3.6 GCC 查看支持的 C 语言标准版本
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 3.6.1 概述
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* GCC 是个跨平台的项目,支持 Windows、Linux 和 MacOS ,那么查看它支持的 C 语言标准版本就非常重要,以防止我们使用了新的 C 语言语法,本地却还是旧的 GCC 支持的 C 语言标准。
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
### 3.6.2 查看支持 C 语言标准版本的方法
2024-10-17 03:20:50 +02:00
2024-10-17 10:56:34 +02:00
* 可以执行如下的命令,查看 GCC 支持的 C 语言标准的版本:
2024-10-17 03:20:50 +02:00
```c
2024-10-17 10:56:34 +02:00
gcc -E -dM - < /dev/null | grep "STDC_VERSION"
2024-10-17 03:20:50 +02:00
```
2024-10-08 05:44:30 +02:00
> [!NOTE]
>
2024-10-17 10:56:34 +02:00
> 其实就是通过 `__STDC_VERSION__` 的值,来查看支持的版本:
>
> * 如果没有查到,则默认是 c89 的标准。
> * 如果是 `#define __STDC_VERSION__ 199901L`,则默认支持的是 C99 标准。
> * 如果是 `#define __STDC_VERSION__ 201112L`,则默认支持是的 C11 标准。
> * 如果是 `#define __STDC_VERSION__ 201710L`,则默认支持的是 C17 标准。
> * 如果是 `#define __STDC_VERSION__ 2023xxL`,则默认支持的是 C23 标准。
>
> 需要说明的是, 在本文撰写之前, C23 标准目前还是草案,并没有完全确定下来。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/47.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 3.6.3 切换 GCC 默认支持的 C 语言标准版本
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
#### 3.6.3.1 环境变量方式
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 可以通过设置一个环境变量,来更改默认的 C 语言的标准版本:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
echo 'export CFLAGS="-std=c11"' >> ~/.bashrc
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
```shell
source ~/.bashrc
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/48.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 验证是否有效:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
echo $CFLAGS
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
![](./assets/49.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
#### 3.6.3.2 CMake 方式
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* CMake 方式最简单了,只需要修改配置文件 CMakeLists.txt 文件,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```txt {6}
cmake_minimum_required(VERSION 3.22.1)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
project(c-study VERSION 1.0 LANGUAGES C)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
# 设置 C 标准
set(CMAKE_C_STANDARD 23)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
...
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
#### 3.6.3.3 命令行方式
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 有的时候,我们临时想验证某个版本的新特性,就可以只用在命令行中添加参数,来改变支持的 C 语言标准版本,如下所示:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
gcc -std=c89 ...
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
```shell
gcc -std=c99 ...
2024-10-17 03:20:50 +02:00
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
gcc -std=c11 ...
2024-10-17 03:20:50 +02:00
```
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
```shell
gcc -std=c17 ...
2024-10-08 05:44:30 +02:00
```
2024-10-17 10:56:34 +02:00
## 3.7 CLion 如何集成 MSYS2?
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 3.7.1 概述
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* CLion 在 Windows 中默认集成的是 `MinGW` ,可能无法满足我们的需求,我们需要使用 `MSYS2` ,因为其提供的包管理器太好用了。
2024-10-08 05:44:30 +02:00
2024-10-17 03:20:50 +02:00
> [!NOTE]
>
2024-10-17 10:56:34 +02:00
> 需要说明的是,`MSYS2` 包含了 `MinGW`,这也是我们为什么在 `Windows` 上为什么使用 `MSYS2` 的其中一个原因。
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 3.7.2 集成方法
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ① 所有设置:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/50.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ② 工具链:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/51.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
## 3.8 CLion 中代码模板的使用
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 3.8.1 概述
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* 在学习 C 语言的过程中,可能会不停的写这样的模板代码,如下所示:
2024-10-08 05:44:30 +02:00
```c
#include <stdio.h>
int main() {
2024-10-17 10:56:34 +02:00
// 禁用 stdout 缓冲区
setbuf(stdout, nullptr);
2024-10-08 05:44:30 +02:00
return 0;
}
```
2024-10-17 10:56:34 +02:00
* 刚开始写,还感觉比较新鲜,非常好玩。但是,随着时间的深入,我们会感觉特别繁琐,又很无聊。那么,能否在 CLion 中配置一下,让其为我们自动生成呢?
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/52.gif)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
### 3.8.2 配置方法
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ① 点击`设置`:
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/53.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ② `编辑器` --> `文件和代码模板` :
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
![](./assets/54.png)
2024-10-08 05:44:30 +02:00
2024-10-17 10:56:34 +02:00
* ③ 点击`+`,配置对应的内容:
2024-10-08 05:44:30 +02:00
2024-10-17 03:20:50 +02:00
> [!NOTE]
2024-10-08 05:44:30 +02:00
>
2024-10-17 10:56:34 +02:00
> 模板的内容,如下所示:
>
> ```c
> #[[#include]]# <stdio.h>
>
> int main() {
>
> // 禁用 stdout 缓冲区
> setbuf(stdout, nullptr);
>
>
>
> return 0;
> }
> ```
![](./assets/55.png)