C 语言进阶:字符串与内存操作库函数模拟实现
作为 C 语言初学者,字符串处理和内存操作是核心重难点,今天我亲手模拟实现了 strlen / strcpy / strcat / strcmp / strncpy / strncat /strstr / memcpy / memmove 9 个经典库函数,从原理到代码逐点吃透,彻底搞懂指针操作与函数底层逻辑!
一、前言
C 语言标准库提供了大量字符串 / 内存操作函数,但知其然更要知其所以然。手动模拟实现这些函数,能深度理解指针运算、字符串结束规则、内存拷贝逻辑,同时规避新手常见 bug。
本文所有实现严格遵循标准库规范,包含边界判断、异常处理,可直接运行学习~
二、字符串操作函数实现
1. my_strlen(字符串长度计算)
核心功能:计算字符串有效字符长度,不包含\0
实现思路:
- 断言判断指针合法性
- 两种经典实现:指针相减法 / 计数器法
- 遍历字符串直到
\0,返回长度
#include<stdio.h>
#include<string.h>
#include<assert.h>
// 方法1:指针相减(效率更高)
size_t my_strlen(const char* str)
{
assert(str);
char* ret = (char*)str;
while (*str)
{
str++;
}
return str - ret;
}
// 方法2:计数器法(更易理解)
size_t my_strlen(const char* str)
{
assert(str);
int count = 0;
while (*str)
{
count++;
str++;
}
return count;
}
2. my_strcpy(字符串拷贝)
核心功能:将源字符串完整拷贝到目标空间,包含\0
关键规范:
- 目标空间必须可修改、足够大
- 源字符串必须以
\0结尾 - 拷贝会连带
\0一起复制
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
// 极简写法:拷贝字符+指针移动,遇到\0自动停止
while (*dest++ = *src++)
{
;
}
return ret;
}
3. my_strcat(字符串追加)
核心功能:将源字符串追加到目标字符串末尾
实现步骤:
- 找到目标字符串末尾的
\0 - 从
\0位置开始拷贝源字符串 - 自动追加结束符
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
// 找到dest末尾
while (*dest)
{
dest++;
}
// 追加字符串
while (*dest++ = *src++)
{
;
}
return ret;
}
4. my_strcmp(字符串比较)
核心功能:按 ASCII 值逐字符比较两个字符串
返回值规则:
- 相等 → 返回
0 - 前者大 → 返回大于 0的数
- 后者大 → 返回小于 0的数
int my_strcmp(const char* dest, const char* src)
{
assert(dest && src);
// 字符相等则继续比较
while (*dest == *src)
{
// 同时到达\0,说明完全相等
if (*dest == '\0')
{
return 0;
}
dest++;
src++;
}
// 返回ASCII差值
return *dest - *src;
}
5. my_strncpy(有限长度字符串拷贝)
进阶功能:最多拷贝num个字符,不足则补\0
解决问题:避免 strcpy 无限制拷贝导致的越界风险
char* my_strncpy(char* dest, const char* src, size_t num)
{
assert(dest && src);
char* start = dest;
// 拷贝有效字符
for (int i = 0; i < num && *src != '\0'; i++)
{
*dest = *src;
dest++;
src++;
}
// 剩余空间补\0
while (dest < start + num)
{
*dest = '\0';
dest++;
}
return start;
}
6. my_strncat(有限长度字符串追加)
进阶功能:最多追加num个字符,手动添加结束符
安全可控:限制追加长度,防止缓冲区溢出
char* my_strncat(char* dest,const char* src, size_t num)
{
assert(dest && src);
char* start = dest;
// 找到目标末尾
while (*dest)
{
dest++;
}
size_t count = 0;
// 有限追加
while (*src != '\0' && count < num)
{
*dest = *src;
dest++;
src++;
count++;
}
// 必须手动加结束符
*dest = '\0';
return start;
}
7. my_strstr(子串查找)
核心功能:在主串中查找子串首次出现位置
经典算法:BF 暴力匹配算法
char* my_strstr(const char* str1, const char* str2)
{
// 空串直接返回原串
if (*str2 == '\0')
{
return (char*)str1;
}
const char* p = str1;
const char* s1 = NULL;
const char* s2 = NULL;
// 遍历主串
while (*p)
{
s1 = p;
s2 = str2;
// 逐字符匹配
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
// 子串匹配完成
if (*s2 == '\0')
return (char*)p;
p++;
}
// 未找到
return NULL;
}
三、内存操作函数实现
字符串函数仅适用于字符类型,memcpy / memmove可操作任意类型内存,是通用内存拷贝工具。
1. my_memcpy(基础内存拷贝)
核心功能:无类型限制内存拷贝,按字节拷贝
注意:不处理内存重叠场景
void* my_memcpy(void* dest, const void* src, size_t count)
{
assert(dest && src);
void* ret = dest;
// 强转为char*,按字节拷贝
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
2. my_memmove(安全内存拷贝)
终极优化:解决内存重叠问题,C 语言最标准的内存拷贝函数
核心逻辑:
- 目标地址 < 源地址 → 从前向后拷贝
- 地址重叠 → 从后向前拷贝
int main()
{
// 测试字符串函数
char arr1[20] = "Hello World";
char arr2[20] = { 0 };
my_strcpy(arr2, arr1);
printf("strcpy: %s\n", arr2);
printf("strlen: %zu\n", my_strlen(arr1));
// 测试内存函数
int arr3[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr3 + 2, arr3, 20);
printf("memmove: ");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr3[i]);
}
return 0;
}
四、核心知识点总结
1. 字符串函数共性
- 以
\0作为结束标志 - 源字符串建议用
const修饰,防止修改 - 必须做指针非空断言
assert
2. 内存函数核心
void*通用指针,适配所有数据类型- 强转
char*实现按字节操作 memmove兼容所有拷贝场景,优先使用
3. 新手避坑指南
=和==混淆:判断相等必须用==- 字符串忘加
\0:导致输出乱码 - void * 不能直接运算:必须强转后操作
- 内存重叠:重叠场景必须用
memmove
手动模拟库函数是 C 语言指针学习的最佳实践。从字符操作到内存操作,从基础函数到安全版本,每一行代码都在夯实底层基础。
这些函数是笔试、面试高频考点,吃透原理,无论做题还是工程开发都能游刃有余!
更多推荐


所有评论(0)