跳到主要内容
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/26 12 浏览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) ;
#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, ...) ;
#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) ;
#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的编写方法
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)
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 编译器的使用技巧
-Wall:显示所有警告
-Wextra:显示额外的警告
-g:生成调试信息
-O2:优化等级2
gcc -Wall -Wextra -g main.c utils.c -o app -lm
6.2.2 调试器的使用技巧
run:运行程序
break:设置断点
continue:继续运行
next:执行下一行
step:进入函数
print:打印变量的值
6.2.3 代码检查工具的使用技巧 valgrind --leak-check=yes ./app
七、模块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
#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
#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;
}
#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 ;
}
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 课后练习
编写程序:使用string.h的函数实现字符串反转
编写程序:使用stdio.h的函数实现文件的读写
编写程序:使用stdlib.h的函数实现动态数组的扩容
编写Makefile:构建一个包含多个源文件的项目
编写CMakeLists.txt:构建一个包含多个源文件的项目
相关免费在线工具 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