强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

C/C++ Linux 开发教程(GCC + CMake) / 01 — C 语言简介与 GCC 环境搭建

C 语言简介与 GCC 环境搭建

1. C 语言历史

C 语言诞生于 1972 年,由 Dennis Ritchie 在贝尔实验室开发,最初用于重写 UNIX 操作系统内核。经过数十年发展,C 语言已成为世界上最重要的编程语言之一。

标准 年份 说明
K&R C 1978 《The C Programming Language》定义的非正式标准
ANSI C (C89) 1989 第一个正式标准,也称 C89 / C90
C99 1999 引入 // 注释、变长数组、stdint.h
C11 2011 多线程支持 _Thread_local、泛型选择 _Generic
C17 2017 Bug 修复版本,无新增特性
C23 2023 最新标准,引入 nullptrconstexpr、属性语法等

💡 提示: GCC 默认使用的标准版本取决于 GCC 版本。建议显式指定 -std= 选项以确保可移植性。


2. C 语言特点

C 语言之所以经久不衰,源于以下核心特点:

  • 底层控制: 可直接操作内存(指针)、访问硬件地址
  • 执行效率: 编译后生成原生机器码,性能接近汇编
  • 可移植性: 一次编写,到处编译——从嵌入式单片机到超级计算机
  • 简洁语法: 关键字仅 32 个(C89),语法精炼
  • 生态丰富: 操作系统、数据库、编译器等基础设施几乎全部用 C 编写

⚠️ 注意: C 语言没有垃圾回收、没有内置的边界检查、没有面向对象支持。它赋予程序员极大的自由,也要求程序员对内存管理负责。


3. 安装 GCC

3.1 Linux

# Debian / Ubuntu
sudo apt update
sudo apt install build-essential

# Fedora
sudo dnf install gcc gcc-c++ make

# Arch Linux
sudo pacman -S base-devel

3.2 macOS

# 安装 Xcode Command Line Tools
xcode-select --install

# 或通过 Homebrew 安装 GCC
brew install gcc

3.3 Windows

推荐使用 MSYS2

# 安装 MSYS2 后,在 MSYS2 终端执行
pacman -S mingw-w64-ucrt-x86_64-gcc

安装完成后,将 C:\msys64\ucrt64\bin 添加到系统 PATH

3.4 验证安装

gcc --version

输出示例:

gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
Copyright (C) 2023 Free Software Foundation, Inc.

4. 第一个 C 程序

创建文件 hello.c

#include <stdio.h>

int main(void)
{
    printf("Hello, World!\n");
    return 0;
}

编译并运行:

gcc -o hello hello.c
./hello

输出:

Hello, World!

代码解析

说明
#include <stdio.h> 引入标准 I/O 库头文件
int main(void) 程序入口点,返回类型为 intvoid 表示不接受命令行参数
printf(...) 标准输出函数,\n 为换行符
return 0 返回 0 表示程序正常退出

💡 提示: main 函数返回 0 是操作系统约定。返回非零值通常表示程序异常退出。


5. 编译流程

C 程序从源代码到可执行文件,经历四个阶段:

源代码(.c) → 预处理 → 编译 → 汇编 → 链接 → 可执行文件

我们可以用 GCC 分步查看每个阶段:

5.1 预处理 (Preprocessing)

gcc -E hello.c -o hello.i

展开所有 #include#define 宏等。hello.i 文件通常非常庞大。

5.2 编译 (Compilation)

gcc -S hello.c -o hello.s

生成汇编代码(.s 文件)。

5.3 汇编 (Assembly)

gcc -c hello.c -o hello.o

生成目标文件(.o),包含机器码但尚未链接外部库。

5.4 链接 (Linking)

gcc hello.o -o hello

将目标文件与库文件链接,生成最终可执行文件。

阶段 输入 输出 命令
预处理 .c .i gcc -E
编译 .i / .c .s gcc -S
汇编 .s .o gcc -c
链接 .o + 库 可执行文件 gcc *.o

6. GCC 常用选项

选项 说明 示例
-o <file> 指定输出文件名 gcc -o prog main.c
-Wall 启用所有常用警告 gcc -Wall main.c
-Wextra 启用额外警告 gcc -Wall -Wextra main.c
-Werror 将警告视为错误 gcc -Werror main.c
-O0 不优化(默认,便于调试) gcc -O0 main.c
-O1 / -O2 / -O3 优化级别递增 gcc -O2 main.c
-Os 优化体积 gcc -Os main.c
-std=c99 指定 C 标准 gcc -std=c99 main.c
-std=c11 使用 C11 标准 gcc -std=c11 main.c
-std=c17 使用 C17 标准 gcc -std=c17 main.c
-g 生成调试信息 gcc -g main.c
-pedantic 严格遵循标准 gcc -pedantic main.c
-I<dir> 添加头文件搜索路径 gcc -I./include main.c
-L<dir> 添加库文件搜索路径 gcc -L./lib main.c
-l<lib> 链接指定库 gcc main.c -lm

⚠️ 注意: 养成使用 -Wall -Wextra 的习惯,许多潜在 bug 会在编译时被发现。


7. 编辑器 / IDE 配置

7.1 VSCode

  1. 安装扩展 C/C++
  2. 安装扩展 C/C++ Extension Pack
  3. Ctrl+Shift+PC/C++: Edit Configurations (UI),设置编译器路径和标准

.vscode/tasks.json 示例:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "gcc",
            "args": [
                "-Wall", "-Wextra", "-std=c17",
                "-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "group": { "kind": "build", "isDefault": true }
        }
    ]
}

7.2 CLion

CLion 使用 CMake 管理项目,自动生成 CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(my_project C)

set(CMAKE_C_STANDARD 17)

add_executable(my_project main.c)

8. 编译多个文件

当项目由多个 .c 文件组成时,需要分别编译再链接:

gcc -c main.c -o main.o
gcc -c utils.c -o utils.o
gcc main.o utils.o -o myapp

或者一步到位:

gcc main.c utils.c -o myapp

💡 提示: 大型项目中建议使用 makeCMake 管理编译流程,避免重复编译未修改的文件。

使用 Makefile 简化

CC = gcc
CFLAGS = -Wall -Wextra -std=c17 -g

myapp: main.o utils.o
	$(CC) $(CFLAGS) -o $@ $^

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

clean:
	rm -f *.o myapp

9. C vs C++:如何选择?

维度 C C++
编译器 gcc g++
文件扩展名 .c .cpp / .cc
面向对象 不支持 完整支持
标准库 精简(libc 丰富(STL)
适用场景 操作系统、嵌入式、驱动 游戏引擎、GUI、大型应用
学习曲线 较低(语法简单) 较高(特性繁多)
内存管理 手动(malloc/free 手动 + RAII + 智能指针

建议:

  • 初学者: 先学 C,理解指针和内存管理
  • 系统编程: 使用 C(Linux 内核、嵌入式固件)
  • 应用开发: 使用 C++(利用 STL 和面向对象)

10. 实际场景:编译一个小型项目

假设项目结构如下:

project/
├── main.c
├── math_utils.c
└── math_utils.h

math_utils.h

#ifndef MATH_UTILS_H
#define MATH_UTILS_H

int add(int a, int b);
int multiply(int a, int b);

#endif

math_utils.c

#include "math_utils.h"

int add(int a, int b)
{
    return a + b;
}

int multiply(int a, int b)
{
    return a * b;
}

main.c

#include <stdio.h>
#include "math_utils.h"

int main(void)
{
    int x = 3, y = 5;
    printf("%d + %d = %d\n", x, y, add(x, y));
    printf("%d * %d = %d\n", x, y, multiply(x, y));
    return 0;
}

编译运行:

gcc -Wall -Wextra -std=c17 -o myapp main.c math_utils.c
./myapp

输出:

3 + 5 = 8
3 * 5 = 15

11. 常见编译错误

错误信息 原因 解决
undefined reference to 'main' 缺少 main 函数 添加 int main(void) { ... }
fatal error: stdio.h: No such file 未安装 C 标准库开发包 sudo apt install build-essential
implicit declaration of function 未声明函数原型 添加函数声明或 #include 对应头文件
segmentation fault 内存访问违规 检查指针和数组越界

12. 扩展阅读