Appearance
[中文版本](/posts/c教程/zh-CN/10-真实项目/091-Designing Small C Libraries)
Writing libraries is how you make your C code reusable, modular, and easy to maintain. In this section, you’ll learn how to design and structure a small, portable, and well-documented C library, the kind used in real systems for decades.
Step 1. What Is a Library in C?
A library in C is a collection of functions and data types that can be used by multiple programs.
There are two kinds of libraries:
- Static libraries (
.aor.lib) – compiled into the final program at build time. - Shared libraries (
.soor.dll) – loaded dynamically at runtime.
You’ll start by building a small static library that provides reusable math utilities.
Step 2. Plan the Library
Let’s design a library called simplemath, which provides:
add,subtract,multiply,divide- Error handling for divide-by-zero
- Clean, consistent naming
Structure:
simplemath/
├── include/
│ └── simplemath.h
├── src/
│ └── simplemath.c
└── MakefileStep 3. The Header File (simplemath.h)
#ifndef SIMPLEMATH_H
#define SIMPLEMATH_H
#ifdef __cplusplus
extern "C" {
#endif
double sm_add(double a, double b);
double sm_sub(double a, double b);
double sm_mul(double a, double b);
double sm_div(double a, double b, int *error);
#ifdef __cplusplus
}
#endif
#endifNotes:
- Include guards prevent double inclusion.
extern "C"allows usage in C++ projects.- Prefix (
sm_) prevents naming conflicts.
Step 4. The Implementation File (simplemath.c)
#include "simplemath.h"
#include <stdio.h>
double sm_add(double a, double b) { return a + b; }
double sm_sub(double a, double b) { return a - b; }
double sm_mul(double a, double b) { return a * b; }
double sm_div(double a, double b, int *error) {
if (b == 0) {
if (error) *error = 1;
fprintf(stderr, "Division by zero\n");
return 0.0;
}
if (error) *error = 0;
return a / b;
}Step 5. Tiny Code: Example Program Using the Library
#include <stdio.h>
#include "simplemath.h"
int main(void) {
int err;
double x = sm_div(10, 2, &err);
printf("10 / 2 = %.2f\n", x);
x = sm_div(10, 0, &err);
if (err) printf("Error detected during division.\n");
return 0;
}Step 6. Makefile to Build the Library
CC = gcc
CFLAGS = -std=c23 -O2 -Wall -Wextra -Iinclude
all: libsimplemath.a test
libsimplemath.a: src/simplemath.o
ar rcs libsimplemath.a src/simplemath.o
src/simplemath.o: src/simplemath.c include/simplemath.h
$(CC) $(CFLAGS) -c src/simplemath.c -o src/simplemath.o
test: test.c libsimplemath.a
$(CC) $(CFLAGS) test.c -L. -lsimplemath -o test
clean:
rm -f src/*.o *.a testBuild it:
makeRun:
./testOutput:
10 / 2 = 5.00
Division by zero
Error detected during division.Step 7. Design Guidelines for Clean C Libraries
| Principle | Description |
|---|---|
| Prefix all symbols | Avoid global name clashes (e.g.,sm_add) |
| Single responsibility | Each function should do one clear thing |
| Minimal dependencies | Don’t rely on non-standard headers |
| Use header guards | Prevent duplicate inclusion |
| Provide error handling | Return codes,errno, or out parameters |
| Write documentation | Use Doxygen or simple comment blocks |
| Version your API | Track breaking changes cleanly |
Step 8. Adding Versioning and Metadata
Add this to your header:
#define SIMPLEMATH_VERSION "1.0.0"In your CMake or Makefile build scripts, you can propagate this version into your packaging system or documentation.
Step 9. Why It Matters
Writing a library transforms you from a script author into a systems builder. It teaches API design, separation of interface and implementation, and long-term maintenance, the same principles used in real-world software like glibc, SQLite, and curl.
Step 10. Try It Yourself
- Add new functions (
sm_pow,sm_mod,sm_avg). - Create a shared version of the library (
libsimplemath.so). - Document your API using Doxygen-style comments.
- Write a header-only version (
static inlinefunctions). - Package your library with versioning and examples.
Next, you’ll learn how to build a full command-line tool in C (92), connecting your reusable libraries to practical, user-facing applications.
