本文整理了 C 语言开发中常用的代码片段,涵盖字符串处理、文件操作、内存管理、时间处理等场景。这些代码经过实际验证,可直接拷贝使用。
字符串处理
安全字符串复制
避免缓冲区溢出的安全复制函数:
safe_strcpy.c - 安全字符串复制
#include#include #include /* 安全字符串复制,自动处理长度和终止符 */ char *safe_strcpy(char *dest, const char *src, size_t dest_size) { if (dest == NULL || src == NULL || dest_size == 0) { return NULL; } size_t len = strlen(src); if (len >= dest_size) { len = dest_size - 1; /* 截断,保留空间给 '\0' */ } memcpy(dest, src, len); dest[len] = '\0'; return dest; } /* 简化版宏 */ #define STRCPY(dst, src) safe_strcpy((dst), (src), sizeof(dst)) int main(void) { char buf[16]; safe_strcpy(buf, "Hello, World!", sizeof(buf)); printf("%s\n", buf); /* 输出: Hello, World! */ safe_strcpy(buf, "This is a very long string that will be truncated", sizeof(buf)); printf("%s\n", buf); /* 输出: This is a very */ return 0; }
字符串分割
类似 Python split 的字符串分割实现:
str_split.c - 字符串分割
#include#include #include typedef struct { char **items; size_t count; } SplitResult; void split_result_free(SplitResult *r) { if (r->items) { for (size_t i = 0; i < r->count; i++) { free(r->items[i]); } free(r->items); } r->items = NULL; r->count = 0; } SplitResult str_split(const char *str, char delim) { SplitResult result = {NULL, 0}; if (str == NULL) return result; size_t len = strlen(str); size_t capacity = 4; result.items = malloc(capacity * sizeof(char *)); if (!result.items) return result; const char *start = str; const char *p = str; while (*p) { if (*p == delim) { size_t tok_len = p - start; char *token = malloc(tok_len + 1); if (token) { memcpy(token, start, tok_len); token[tok_len] = '\0'; if (result.count >= capacity) { capacity *= 2; result.items = realloc(result.items, capacity * sizeof(char *)); } result.items[result.count++] = token; } start = p + 1; } p++; } /* 处理最后一个字段 */ size_t tok_len = p - start; if (tok_len > 0 || (tok_len == 0 && len == 0)) { char *token = malloc(tok_len + 1); if (token) { memcpy(token, start, tok_len); token[tok_len] = '\0'; result.items[result.count++] = token; } } return result; } int main(void) { SplitResult r = str_split("apple,banana,orange,grape", ','); for (size_t i = 0; i < r.count; i++) { printf("[%zu] %s\n", i, r.items[i]); } split_result_free(&r); return 0; }
文件操作
读取整个文件到内存
一次性读取文件全部内容:
read_file.c - 读取整个文件
#include#include /* 读取文件到内存,返回内容并通过 out_size 返回大小 */ char *read_file(const char *path, size_t *out_size) { FILE *fp = fopen(path, "rb"); if (!fp) return NULL; fseek(fp, 0, SEEK_END); long size = ftell(fp); fseek(fp, 0, SEEK_SET); if (size < 0) { fclose(fp); return NULL; } char *content = malloc(size + 1); if (!content) { fclose(fp); return NULL; } size_t read = fread(content, 1, size, fp); content[read] = '\0'; fclose(fp); if (out_size) *out_size = read; return content; } /* 写入文件 */ int write_file(const char *path, const char *content, size_t size) { FILE *fp = fopen(path, "wb"); if (!fp) return -1; size_t written = fwrite(content, 1, size, fp); fclose(fp); return (written == size) ? 0 : -1; } int main(void) { size_t size; char *content = read_file("test.txt", &size); if (content) { printf("Read %zu bytes: %s\n", size, content); free(content); } return 0; }
内存管理
内存池分配器
预先分配内存池,避免频繁 malloc:
mem_pool.c - 简单内存池
#include#include #include typedef struct MemPool { char *buffer; size_t capacity; size_t offset; } MemPool; void pool_init(MemPool *pool, size_t capacity) { pool->buffer = malloc(capacity); pool->capacity = capacity; pool->offset = 0; } void *pool_alloc(MemPool *pool, size_t size) { /* 8 字节对齐 */ size_t aligned = (size + 7) & ~7; if (pool->offset + aligned > pool->capacity) { return NULL; } void *ptr = pool->buffer + pool->offset; pool->offset += aligned; return ptr; } void pool_reset(MemPool *pool) { pool->offset = 0; } void pool_destroy(MemPool *pool) { free(pool->buffer); pool->buffer = NULL; } /* 便捷宏,每次分配时自动计算类型大小 */ #define POOL_ALLOC(pool, type) ((type *)pool_alloc((pool), sizeof(type))) int main(void) { MemPool pool; pool_init(&pool, 4096); int *a = POOL_ALLOC(&pool, int); double *b = POOL_ALLOC(&pool, double); char *c = pool_alloc(&pool, 128); *a = 42; *b = 3.14; strcpy(c, "Hello from pool!"); printf("a=%d, b=%f, c=%s\n", *a, *b, c); printf("Used: %zu / %zu bytes\n", pool.offset, pool.capacity); pool_destroy(&pool); return 0; }
时间处理
高精度计时器
使用 clock_gettime 实现微秒级精度计时:
high_res_timer.c - 高精度计时器
#include#include #include typedef struct { struct timespec start; struct timespec end; } Timer; void timer_start(Timer *t) { clock_gettime(CLOCK_MONOTONIC, &t->start); } void timer_stop(Timer *t) { clock_gettime(CLOCK_MONOTONIC, &t->end); } double timer_elapsed_ms(Timer *t) { double s = (t->end.tv_sec - t->start.tv_sec) * 1000.0; double ns = (t->end.tv_nsec - t->start.tv_nsec) / 1000000.0; return s + ns; } double timer_elapsed_us(Timer *t) { double s = (t->end.tv_sec - t->start.tv_sec) * 1000000.0; double ns = (t->end.tv_nsec - t->start.tv_nsec) / 1000.0; return s + ns; } /* 简单性能测试宏 */ #define BENCHMARK(name, code) do { \ Timer _t; \ timer_start(&_t); \ code; \ timer_stop(&_t); \ printf(name " took %.2f ms\n", timer_elapsed_ms(&_t)); \ } while(0) int main(void) { Timer t; timer_start(&t); /* 模拟一些工作 */ volatile long sum = 0; for (int i = 0; i < 100000000; i++) { sum += i; } timer_stop(&t); printf("elapsed: %.2f ms (%.2f us)\n", timer_elapsed_ms(&t), timer_elapsed_us(&t)); return 0; }
错误处理工具
断言与错误检查宏
实用的调试和错误处理宏:
error_macros.c - 错误处理宏
#include#include #include /* 条件断言,为真则输出警告 */ #define ASSERT(cond, msg) do { \ if (!(cond)) fprintf(stderr, "Assertion failed: %s\n", msg); \ } while(0) /* 条件致命错误,为假则打印并退出 */ #define REQUIRE(cond, msg) do { \ if (!(cond)) { \ fprintf(stderr, "Error: %s\n", msg); \ exit(EXIT_FAILURE); \ } \ } while(0) /* 检查函数返回值,为负则打印错误并goto到错误标签 */ #define CHECK(call) do { \ int _err = (call); \ if (_err < 0) { \ perror(#call); \ goto err; \ } \ } while(0) /* 检查空指针 */ #define NULL_CHECK(ptr) REQUIRE((ptr) != NULL, #ptr " is NULL") /* 简化错误处理函数 */ void die(const char *msg) { fprintf(stderr, "Fatal: %s\n", msg); exit(EXIT_FAILURE); } void die_errno(const char *msg) { perror(msg); exit(EXIT_FAILURE); } int main(void) { /* 示例用法 */ FILE *fp = fopen("nonexistent.txt", "r"); if (!fp) { die_errno("Failed to open file"); } fclose(fp); return 0; }
容器实现
动态数组
类似 std::vector 的动态数组实现:
dynamic_array.c - 动态数组容器
#include#include #include #define DA_INIT_CAP 4 typedef struct { int *data; size_t size; size_t capacity; } DynamicArray; void da_init(DynamicArray *da) { da->data = malloc(DA_INIT_CAP * sizeof(int)); da->size = 0; da->capacity = DA_INIT_CAP; } void da_push(DynamicArray *da, int val) { if (da->size >= da->capacity) { da->capacity *= 2; da->data = realloc(da->data, da->capacity * sizeof(int)); } da->data[da->size++] = val; } void da_free(DynamicArray *da) { free(da->data); da->data = NULL; da->size = da->capacity = 0; } /* 泛型版本 - 用宏实现 */ #define DA_TYPE(type, name) typedef struct { \ type *data; \ size_t size; \ size_t capacity; \ } name; \ void name##_init(name *da) { \ da->data = malloc(4 * sizeof(type)); \ da->size = 0; \ da->capacity = 4; \ } \ void name##_push(name *da, type val) { \ if (da->size >= da->capacity) { \ da->capacity *= 2; \ da->data = realloc(da->data, da->capacity * sizeof(type)); \ } \ da->data[da->size++] = val; \ } \ void name##_free(name *da) { \ free(da->data); \ da->data = NULL; \ da->size = da->capacity = 0; \ } DA_TYPE(char, CharArray) DA_TYPE(double, DoubleArray) int main(void) { DynamicArray arr; da_init(&arr); for (int i = 0; i < 100; i++) { da_push(&arr, i * 10); } printf("size=%zu, capacity=%zu\n", arr.size, arr.capacity); printf("arr[50]=%d\n", arr.data[50]); da_free(&arr); return 0; }
总结
这些代码片段涵盖了 C 语言开发中的高频场景。建议将这些代码保存为独立的头文件或源文件,需要时直接 include 即可。祝编码愉快!