C语言基础教程:Clang的安装与环境变量配置

去年两次参加软考高级架构师考试,都是在某个老牌顶级名校,在他们的书店里发现很多教材用的还是VC98之类的古董。这玩意儿在我们当年学的时候就已经显得陈旧了。

前些年就开始教授基础的编程入门课程,既教Python,也教C语言基础知识。我教学时一般使用苏小红老师的教材,其中有一些章节是孙志岗老师编写的,他们采用的是Code Blocks,这个工具也还不错,可以安装集成GCC的版本,网上资料也很丰富。

但从今年开始,我考虑换一个思路。今年准备采用Clang,Clang是LLVM项目提供的现代化C/C++/Objective-C编译器,以编译快、内存省、报错清晰著称。Clang可以搭配Void/Trae/Qoder之类的现代编辑器,以及之前我们介绍过的OpenCode和Ollama,让同学们能够直接使用当前最前沿的工具链。

下面就简单介绍一下如何安装Clang以及配置环境变量。

Windows 系统下使用 Winget 安装

如果你使用的是Windows系统,建议尽量多用Winget,而不要去网站下载安装包,这样既能提高安全性,也能省去很多麻烦。

如何使用Winget呢?很简单,按下快捷键Win+X,然后点击"终端(管理员)",如下图所示:

这样就能进入PowerShell,注意一定要是PowerShell,不能是cmd,因为命令不一样。

winget install LLVM.LLVM

然后默认安装位置在

C:\Program Files\LLVM\bin

Windows 系统下环境变量设置

刚安装完成时,你直接运行clang肯定会出错,会提示类似下面的错误信息:

clang
clang : The term 'clang' is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was included, verify that the path is
correct and try again.
At line:1 char:1
+ clang
+ ~~~~~
    + CategoryInfo          : ObjectNotFound: (clang:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

这是因为刚刚安装好的clang目录没有被添加到系统的环境变量里,所以系统找不到它,这时候就需要手动将上述目录添加到环境变量中。

这也很简单,还是按Win+X,选择"终端(管理员)",进入PowerShell,注意一定要是PowerShell,不能是cmd,因为命令不一样。 然后运行下面这段命令,注意仔细复制粘贴,不要遗漏任何字符:

[Environment]::SetEnvironmentVariable("Path", $([Environment]::GetEnvironmentVariable("Path","Machine")) + ";C:\Program Files\LLVM\bin", "Machine")

上面的命令执行成功后,需要新建一个终端窗口(注意,一定要是新建的),才能加载新设置的环境变量,然后再运行验证命令。

clang --version

会得到

clang version 21.1.8
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin

Ubuntu 系统下的安装和使用

如果使用的是Ubuntu系统,那就更方便了,直接使用apt安装即可:

# 首先更新软件包列表
sudo apt update
# 然后安装Clang本体
sudo apt install clang
# 接着安装一些依赖库
sudo apt install libc++-dev libc++abi-dev
# 然后就可以直接使用了
clang --version

就会得到下面的输出:

Ubuntu clang version 18.1.3 (1ubuntu1)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Clang 的最基础用法

假设当前目录下有一份名为hello.c的C语言代码文件,内容如下:

#include <stdio.h>      // 标准输入输出(printf, scanf)
#include <stdlib.h>     // 标准库(malloc, free, EXIT_SUCCESS)
#include <string.h>     // 字符串操作(strcpy, strlen)
#include <math.h>       // 数学函数(sqrt, pow)
#include <stdbool.h>    // 布尔类型(bool, true, false)

// 函数声明(可选,因定义在 main 之后)
double compute_hypotenuse(double a, double b);

int main(void) {
    // === 基本数据类型 ===
    int          age = 25;                     // 整型
    short        count = 100;                  // 短整型
    long         big_num = 123456789L;         // 长整型
    long long    huge_num = 9876543210LL;      // 更长整型

    float        price = 19.99f;               // 单精度浮点
    double       pi = 3.1415926535;            // 双精度浮点

    char         grade = 'A';                  // 字符(ASCII)
    unsigned char byte_val = 255;              // 无符号字符

    bool         is_valid = true;              // 布尔值(C99起)

    // === 构造类型:数组、结构体、枚举 ===
    int scores[3] = {90, 85, 95};              // 数组

    struct Student {                           // 结构体
        char name[20];
        int age;
        double gpa;
    } stu = {"Alice", 20, 3.8};

    enum Color { RED, GREEN, BLUE };           // 枚举
    enum Color bg = GREEN;

    // === 指针与动态内存 ===
    int *p = &age;                             // 指针(指向 age)
    int *arr = malloc(5 * sizeof(int));        // 动态分配数组
    if (arr == NULL) return EXIT_FAILURE;
    for (int i = 0; i < 5; i++) arr[i] = i * 2;

    // === 使用标准库函数 ===
    printf("Hello, %s! Age: %d\n", stu.name, stu.age);
    printf("Pi is about %.6f, sqrt(2) is about %.4f\n", pi, sqrt(2.0));
    printf("Hypotenuse of (3,4): %.2f\n", compute_hypotenuse(3.0, 4.0));

    // === 控制结构 ===
    if (is_valid) {
        printf("Status: Valid\n");
    }

    for (int i = 0; i < 3; i++) {
        printf("Score[%d] = %d\n", i, scores[i]);
    }

    // === 释放动态内存 ===
    free(arr);

    return EXIT_SUCCESS;  // 程序正常退出
}

// === 自定义函数 ===
double compute_hypotenuse(double a, double b) {
    return sqrt(a * a + b * b);  // 调用 math.h 中的 sqrt
}

上面的代码内容可能比较多,其实涵盖了C语言的基础知识点,大家现在不用太在意细节。

# 编译 C 程序
clang hello.c -o hello.exe
./hello.exe

然后就会得到类似下面的输出:

Hello, Alice! Age: 20
Pi is about 3.141593, sqrt(2) is about 1.4142
Hypotenuse of (3,4): 5.00
Status: Valid
Score[0] = 90
Score[1] = 85
Score[2] = 95

上面使用了.exe扩展名,这是针对Windows用户的。 在Unix-like系统(如Linux或macOS)中,可执行文件通常不带.exe后缀;.exe是Windows的惯用命名方式。因此在这些系统中建议输出为hello而非hello.exe,如下所示:

# 编译 C 程序
clang hello.c -o hello
./hello

Clang 的进阶使用

其实前面的编译过程还可以添加很多选项。另外,严格来说这里实际上完成了编译、链接等多个步骤,只是在此处简称为编译。

选项 作用
-std=c11 指定使用C11标准(推荐,因代码使用了bool等C99+特性)
-O2 启用推荐的优化等级,适用于发布版本
-g 生成调试信息,便于使用GDB或LLDB调试
-Wall 开启常见警告,帮助发现潜在问题
-Wextra 启用更多额外警告(可选但推荐)
-lm 在Linux或macOS下链接数学库(因代码调用了sqrtpow

重要:在Linux或macOS系统下,链接数学库时,-lm选项必须放在源文件之后,否则可能导致链接失败:

clang -std=c11 -O2 -Wall -g hello.c -o hello.exe   # ✅ Windows
clang -std=c11 -O2 -Wall -g hello.c -lm -o hello   # ✅ Linux或macOS
clang -lm hello.c -o hello                         # ❌ 可能报错

完整推荐命令:

clang -std=c11 -O2 -Wall -Wextra -g hello.c -o hello.exe   # ✅ Windows
clang -std=c11 -O2 -Wall -Wextra -g hello.c -lm -o hello   # ✅ Linux或macOS

Clang 的简单静态分析

Clang内置静态分析器,可以在不运行程序的情况下发现空指针解引用、未初始化变量等问题:

clang --analyze hello.c

就会提示

hello.c:38:10: warning: Value stored to 'p' during its initialization is never read
      [deadcode.DeadStores]
   38 |     int *p = &age;                             // 指针(指向 age)
      |          ^   ~~~~
1 warning generated.

若代码中存在如malloc失败未处理等风险,分析器会给出相应提示。

如果你想要了解编译器如何理解你的代码:

clang -S -emit-llvm hello.c -o hello.ll

生成的hello.ll是人类可读的LLVM IR,可用于学习编译原理或进行手动优化。

Category: C
Category
Tagcloud
FckZhiHu AI Nvidia Game Windows11 IDE Poem Science macOS Photography Qwen3 PyOpenCL AI,Data Science Visualization GlumPy Ollama Translate Learning Programming Communicate Virtualization LTO ChromeBook Scholar Software Life Windows Kivy MayaVi PVE Hackintosh GIS Chat Hardware Lesson Ubuntu Cursor Book Tools Discuss NixOS Mac FuckChunWan Camera VisPy Conda Hack Shit Pyenv LlamaFactory PHD C Translation Hadoop Python VM Server OpenWebUI Video Code Generation CUDA RaspberryPi SandBox LTFS GPT-OSS Radio Virtual Machine University Geology 耳机 GeoPython 音频 Tape Linux ML QGIS OpenCL Lens Junck VTK FuckZhihu TUNA Mount&Blade Microscope Memory Tool Code Raspbian Story RTL-SDR HBase QEMU History VirtualMachine NAS Data n8n AIGC Photo 蓝牙