跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C

C语言标准库与工具链:string.h、stdio.h、stdlib.h及CMake构建

C语言标准库涵盖string.h字符串处理、stdio.h输入输出、stdlib.h内存管理等核心功能。文章详解strcpy、printf、malloc等常用函数用法及安全注意事项,如避免溢出和内存泄漏。同时介绍CMake与Makefile构建流程,以及gcc编译、gdb调试、valgrind检查等工具链技巧,并通过实战案例展示如何组织项目结构完成构建。

岁月神偷发布于 2026/3/16更新于 2026/4/2612 浏览
C语言标准库与工具链:string.h、stdio.h、stdlib.h及CMake构建

C语言标准库与常用工具链:string.h、stdio.h、stdlib.h深度解析与CMake、Makefile构建

一、前言:为什么C标准库与工具链是C语言开发的基石?

学习目标
  • 理解C标准库的本质:C语言的标准函数库,提供了大量常用函数
  • 理解工具链的本质:用于编译、链接和调试C语言程序的工具集合
  • 明确C标准库与工具链的重要性:提高开发效率、简化程序结构
  • 掌握本章学习重点:string.h、stdio.h、stdlib.h的常用函数、CMake与Makefile的构建方法、工具链的使用技巧、避坑指南、实战案例分析
  • 学会使用C标准库编写高效、简洁的程序,使用工具链构建项目
重点提示

💡 C标准库与工具链是C语言开发的基石!通过C标准库,你可以直接使用大量常用函数,避免重复造轮子;通过工具链,你可以简化项目的构建和调试过程。


二、模块1:string.h深度解析——字符串处理的常用函数

2.1 学习目标
  • 理解字符串处理的本质:对字符串进行操作,如复制、拼接、比较
  • 掌握string.h的常用函数:strcpy、strncpy、strcat、strncat、strcmp、strncmp、strlen、strchr、strstr
  • 掌握字符串处理的避坑指南:避免字符串溢出、避免空指针
  • 避开string.h使用的3大常见坑
2.2 string.h的常用函数

字符串复制:

#include <string.h>
char* strcpy(char* dest, const char* src);
char* strncpy(char* dest, const char* src, size_t n);

字符串拼接:

#include <string.h>
char* strcat(char* dest, const char* src);
char* ;
strncat
(char* dest, const char* src, size_t n)

字符串比较:

#include <string.h>
int strcmp(const char* s1, const char* s2);
int strncmp(const char* s1, const char* s2, size_t n);

字符串长度:

#include <string.h>
size_t strlen(const char* s);

代码示例1:使用string.h的常用函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char str1[50] = "Hello, ";
    char str2[] = "World!";
    char str3[50];

    // 字符串复制
    strncpy(str3, str1, sizeof(str3));
    str3[sizeof(str3) - 1] = '\0';
    printf("str3: %s\n", str3);

    // 字符串拼接
    strncat(str3, str2, sizeof(str3) - strlen(str3) - 1);
    printf("str3: %s\n", str3);

    // 字符串比较
    int cmp = strcmp(str1, str2);
    if (cmp < 0) {
        printf("str1 < str2\n");
    } else if (cmp > 0) {
        printf("str1 > str2\n");
    } else {
        printf("str1 == str2\n");
    }

    // 字符串长度
    printf("str1的长度:%lu\n", strlen(str1));

    // 查找字符
    char* ptr = strchr(str1, ',');
    if (ptr != NULL) {
        printf("找到字符 ',' 在位置:%ld\n", ptr - str1);
    }

    // 查找子字符串
    ptr = strstr(str3, "World");
    if (ptr != NULL) {
        printf("找到子字符串 \"World\" 在位置:%ld\n", ptr - str3);
    }

    return 0;
}

三、模块2:stdio.h深度解析——标准输入输出的常用函数

3.1 学习目标
  • 理解标准输入输出的本质:与用户或文件进行数据交换
  • 掌握stdio.h的常用函数:printf、scanf、fprintf、fscanf、fopen、fclose、fread、fwrite
  • 掌握标准输入输出的避坑指南:避免文件打开失败、避免文件读取失败、避免文件写入失败
  • 避开stdio.h使用的3大常见坑
3.2 stdio.h的常用函数

控制台输入输出:

#include <stdio.h>
int printf(const char* format, ...);
int scanf(const char* format, ...);

文件输入输出:

#include <stdio.h>
FILE * fopen(const char* filename, const char* mode);
int fclose(FILE * stream);
size_t fread(void* ptr, size_t size, size_t nmemb, FILE * stream);
size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE * stream);
int fprintf(FILE * stream, const char* format, ...);
int fscanf(FILE * stream, const char* format, ...);

代码示例2:使用stdio.h的常用函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char name[50];
    int age;
    float score;
} Student;

int main() {
    Student students[3] = { {"张三", 20, 90.5}, {"李四", 21, 85.5}, {"王五", 22, 95.5} };

    // 写文件
    FILE * fp = fopen("students.txt", "w");
    if (fp == NULL) {
        printf("文件打开失败!\n");
        return 0;
    }
    for (int i = 0; i < 3; i++) {
        fprintf(fp, "姓名:%s,年龄:%d,成绩:%f\n", students[i].name, students[i].age, students[i].score);
    }
    fclose(fp);

    // 读文件
    char buffer[1024];
    fp = fopen("students.txt", "r");
    if (fp == NULL) {
        printf("文件打开失败!\n");
        return 0;
    }
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        printf("%s", buffer);
    }
    fclose(fp);

    // 二进制文件读写
    fp = fopen("students.dat", "wb");
    if (fp == NULL) {
        printf("文件打开失败!\n");
        return 0;
    }
    fwrite(students, sizeof(Student), 3, fp);
    fclose(fp);

    Student read_students[3];
    fp = fopen("students.dat", "rb");
    if (fp == NULL) {
        printf("文件打开失败!\n");
        return 0;
    }
    fread(read_students, sizeof(Student), 3, fp);
    fclose(fp);

    printf("二进制文件读取结果:\n");
    for (int i = 0; i < 3; i++) {
        printf("姓名:%s,年龄:%d,成绩:%f\n", read_students[i].name, read_students[i].age, read_students[i].score);
    }

    return 0;
}

四、模块3:stdlib.h深度解析——动态内存管理与常用工具函数

4.1 学习目标
  • 理解动态内存管理的本质:在程序运行过程中动态分配和释放内存
  • 掌握stdlib.h的常用函数:malloc、calloc、realloc、free、atoi、atof、rand、srand
  • 掌握动态内存管理的避坑指南:避免内存泄漏、避免空指针、避免访问已释放的内存
  • 避开stdlib.h使用的3大常见坑
4.2 stdlib.h的常用函数

动态内存管理:

#include <stdlib.h>
void* malloc(size_t size);
void* calloc(size_t nmemb, size_t size);
void* realloc(void* ptr, size_t size);
void free(void* ptr);

类型转换:

#include <stdlib.h>
int atoi(const char* nptr);
double atof(const char* nptr);

随机数:

#include <stdlib.h>
int rand(void);
void srand(unsigned int seed);

代码示例3:使用stdlib.h的常用函数

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    int* ptr;
    int size = 5;

    // 动态内存分配
    ptr = (int*) malloc(size * sizeof(int));
    if (ptr == NULL) {
        printf("内存分配失败!\n");
        return 0;
    }

    // 初始化数组
    srand(time(NULL));
    for (int i = 0; i < size; i++) {
        ptr[i] = rand() % 100;
    }

    // 打印数组
    printf("数组:");
    for (int i = 0; i < size; i++) {
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 重新分配内存
    size = 10;
    ptr = (int*) realloc(ptr, size * sizeof(int));
    if (ptr == NULL) {
        printf("内存分配失败!\n");
        return 0;
    }

    // 初始化新分配的内存
    for (int i = 5; i < size; i++) {
        ptr[i] = rand() % 100;
    }

    // 打印数组
    printf("数组:");
    for (int i = 0; i < size; i++) {
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 释放内存
    free(ptr);
    ptr = NULL;

    // 类型转换
    char str1[] = "123";
    char str2[] = "3.14";
    int num = atoi(str1);
    double fnum = atof(str2);
    printf("num:%d,fnum:%f\n", num, fnum);

    return 0;
}

五、模块4:CMake与Makefile构建——简化项目的构建过程

5.1 学习目标
  • 理解构建工具的本质:用于管理项目的编译、链接和安装过程
  • 掌握Makefile的编写方法:规则、变量、函数
  • 掌握CMake的使用方法:CMakeLists.txt的编写、构建过程
  • 掌握构建工具的避坑指南:避免语法错误、避免依赖关系错误、避免链接错误
  • 避开构建工具使用的3大常见坑
5.2 Makefile的编写方法

代码示例4:Makefile示例

# 编译器
CC := gcc
# 编译选项
CFLAGS := -Wall -Wextra -g
# 链接选项
LDFLAGS := -lm
# 源文件
SRCS := main.c utils.c
# 目标文件
OBJS := $(SRCS:.c=.o)
# 可执行文件
TARGET := app

.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJS)
	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@
clean:
	rm -f $(OBJS) $(TARGET)

代码示例5:CMakeLists.txt示例

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 设置C标准
set(CMAKE_C_STANDARD 11)

# 源文件
set(SRCS main.c utils.c)

# 目标可执行文件
add_executable(app ${SRCS})

# 链接库
target_link_libraries(app m)

# 安装目标
install(TARGETS app RUNTIME DESTINATION bin)

六、模块5:工具链的使用技巧——提高开发效率

6.1 学习目标
  • 理解工具链的本质:用于编译、链接和调试C语言程序的工具集合
  • 掌握编译器的使用技巧:gcc的常用选项、优化选项
  • 掌握调试器的使用技巧:gdb的常用命令、断点设置
  • 掌握代码检查工具的使用技巧:valgrind、cppcheck
  • 避开工具链使用的3大常见坑
6.2 工具链的使用技巧
6.2.1 编译器的使用技巧

gcc的常用选项:

  • -Wall:显示所有警告
  • -Wextra:显示额外的警告
  • -g:生成调试信息
  • -O2:优化等级2

代码示例6:使用gcc编译程序

gcc -Wall -Wextra -g main.c utils.c -o app -lm
6.2.2 调试器的使用技巧

gdb的常用命令:

  • run:运行程序
  • break:设置断点
  • continue:继续运行
  • next:执行下一行
  • step:进入函数
  • print:打印变量的值

代码示例7:使用gdb调试程序

gdb app
6.2.3 代码检查工具的使用技巧

valgrind的使用:

valgrind --leak-check=yes ./app

cppcheck的使用:

cppcheck main.c utils.c

七、模块6:实战案例分析——使用C标准库与工具链构建项目

7.1 学习目标
  • 掌握使用C标准库与工具链构建项目:使用string.h、stdio.h、stdlib.h编写程序,使用CMake与Makefile构建项目
  • 学会使用C标准库与工具链解决实际问题
  • 避开实战案例使用的3大常见坑
7.2 使用C标准库与工具链构建项目

项目结构:

myproject/
├── CMakeLists.txt
├── Makefile
├── include/
│   └── utils.h
└── src/
    ├── main.c
    └── utils.c

utils.h:

#ifndef UTILS_H
#define UTILS_H

int sum(int* arr, int size);
int max(int* arr, int size);
int min(int* arr, int size);

#endif

utils.c:

#include "utils.h"

int sum(int* arr, int size) {
    int total = 0;
    for (int i = 0; i < size; i++) {
        total += arr[i];
    }
    return total;
}

int max(int* arr, int size) {
    int maximum = arr[0];
    for (int i = 1; i < size; i++) {
        if (arr[i] > maximum) {
            maximum = arr[i];
        }
    }
    return maximum;
}

int min(int* arr, int size) {
    int minimum = arr[0];
    for (int i = 1; i < size; i++) {
        if (arr[i] < minimum) {
            minimum = arr[i];
        }
    }
    return minimum;
}

main.c:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "utils.h"

#define SIZE 10

int main() {
    int* arr = (int*) malloc(SIZE * sizeof(int));
    if (arr == NULL) {
        printf("内存分配失败!\n");
        return 0;
    }

    srand(time(NULL));
    for (int i = 0; i < SIZE; i++) {
        arr[i] = rand() % 100;
    }

    printf("数组:");
    for (int i = 0; i < SIZE; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    printf("和:%d\n", sum(arr, SIZE));
    printf("最大值:%d\n", max(arr, SIZE));
    printf("最小值:%d\n", min(arr, SIZE));

    free(arr);
    arr = NULL;

    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(MyProject)

set(CMAKE_C_STANDARD 11)
include_directories(include)
set(SRCS src/main.c src/utils.c)
add_executable(app ${SRCS})
install(TARGETS app RUNTIME DESTINATION bin)

构建过程:

mkdir build
cd build
cmake ..
make
./app

八、本章总结与课后练习

8.1 总结

✅ string.h深度解析:字符串处理的常用函数,包括复制、拼接、比较、查找
✅ stdio.h深度解析:标准输入输出的常用函数,包括控制台输入输出和文件输入输出
✅ stdlib.h深度解析:动态内存管理与常用工具函数,包括动态内存分配、类型转换、随机数
✅ CMake与Makefile构建:简化项目的构建过程,提高开发效率
✅ 工具链的使用技巧:提高开发效率,包括编译器、调试器、代码检查工具
✅ 实战案例分析:使用C标准库与工具链构建项目,实现数组的求和、求最大值、求最小值

8.2 课后练习
  1. 编写程序:使用string.h的函数实现字符串反转
  2. 编写程序:使用stdio.h的函数实现文件的读写
  3. 编写程序:使用stdlib.h的函数实现动态数组的扩容
  4. 编写Makefile:构建一个包含多个源文件的项目
  5. 编写CMakeLists.txt:构建一个包含多个源文件的项目

目录

  1. C语言标准库与常用工具链:string.h、stdio.h、stdlib.h深度解析与CMake、Makefile构建
  2. 一、前言:为什么C标准库与工具链是C语言开发的基石?
  3. 学习目标
  4. 重点提示
  5. 二、模块1:string.h深度解析——字符串处理的常用函数
  6. 2.1 学习目标
  7. 2.2 string.h的常用函数
  8. 三、模块2:stdio.h深度解析——标准输入输出的常用函数
  9. 3.1 学习目标
  10. 3.2 stdio.h的常用函数
  11. 四、模块3:stdlib.h深度解析——动态内存管理与常用工具函数
  12. 4.1 学习目标
  13. 4.2 stdlib.h的常用函数
  14. 五、模块4:CMake与Makefile构建——简化项目的构建过程
  15. 5.1 学习目标
  16. 5.2 Makefile的编写方法
  17. 编译器
  18. 编译选项
  19. 链接选项
  20. 源文件
  21. 目标文件
  22. 可执行文件
  23. 设置C标准
  24. 源文件
  25. 目标可执行文件
  26. 链接库
  27. 安装目标
  28. 六、模块5:工具链的使用技巧——提高开发效率
  29. 6.1 学习目标
  30. 6.2 工具链的使用技巧
  31. 6.2.1 编译器的使用技巧
  32. 6.2.2 调试器的使用技巧
  33. 6.2.3 代码检查工具的使用技巧
  34. 七、模块6:实战案例分析——使用C标准库与工具链构建项目
  35. 7.1 学习目标
  36. 7.2 使用C标准库与工具链构建项目
  37. 八、本章总结与课后练习
  38. 8.1 总结
  39. 8.2 课后练习
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 2025 大模型产品经理转型指南:从零开始掌握核心技能与实战路径
  • GitHub Copilot Pro 学生免费认证与 VS Code 集成指南
  • Java 自旋锁与读写锁详解
  • 汽车参数对比爬虫实战:从静态页面到动态渲染的Python技术栈解析
  • VS Code 远程配置 GitHub Copilot 无法使用的排查与避坑指南
  • openTCS WEB 接口实战:从基础调用到自定义指令开发
  • FPGA 光通信开发:Aurora 64B/66B 协议使用指南
  • Adobe Illustrator 2025 安装步骤与使用技巧指南
  • 基于 OpenClaw 与飞书搭建多 Agent AI 助理团队
  • Moon VR Video Player 使用指南:支持 8K/12K 多音轨及外挂字幕
  • 基于 Spring AI 和 Claude 构建企业智能客服系统:从架构到实践
  • Python AI 入门:从线性回归到图像分类
  • ESP32 开发板搭建同步 WebServer 服务
  • 前端使用 Document Picture-in-Picture API 实现视频小窗同步控制
  • 医疗系统文档集中标准化存储与 AI 智能化更新路径
  • Clawdbot 开源 AI 助手国内部署教程:镜像加速与环境配置
  • ERNIE-4.5-0.3B 超轻量模型部署与测评指南
  • 前端开发核心计算机基础知识梳理
  • cJSON 1.7.19 源码深度分析:数据结构与解析实现
  • KaiwuDB 在 PX4-ROS2 无人机仿真中的时序数据存储实践

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online