C语言常用字符串与内存处理函数底层实现解析

Oliver
Oliver
发布时间:2026-10-13 | 3人浏览过
原创

深入理解 C 语言核心库函数的内部机制,掌握 memcpy、memmove、strlen、strcpy、strcmp、strstr 与 strcat 的模拟实现。文章结合内存重叠等常见陷阱,提供多种算法思路(如递归、双指针)及完整代码片段。

一、内存拷贝:memcpy 与 memmove

memcpy 用于将 src 指向的内存区域向前拷贝到 dst,按字节操作,不涉及类型转换,遇到 "\0" 不会停止。由于它是简单的从左向右覆盖,当源地址与目标地址发生重叠时(即源起始地址低于目标起始地址),数据会被覆盖导致错误结果。此时应使用 memmove,它能智能处理内存重叠问题。

void *Mymemcpy(void *dst, const void *src, int len){
	void *ret = dst;
	assert(src);
	assert(dst);
	while (len--){
		*(char *)dst = *(char *)src;
		dst = (char *)dst + 1;
		src = (char *)src + 1;
	}
	return ret;
}
int main(){
	char str[100] = "ABCDE";
	// 将第3个字符开始的2个字节覆盖到开头
	Mymemcpy(str, str + 2, 2);
	printf("%s", str);
	return 0;
}

上述测试用例中,源字符串首地址 str+2 低于目标首地址 str,从左向右拷贝导致前两个字符被后续字符覆盖,产生意料之外的输出。

为解决此问题,引入 Mymemmove。当检测到来地址小于目标地址且存在重叠范围时,改为从右向左进行拷贝,从而保证数据不被意外覆盖。

二、memmove 的模拟实现

memmove 的核心在于判断地址重叠情况:if (_dst > _src && _dst < _src + len)。若满足条件,则从末尾开始倒序拷贝;否则保持正向拷贝。

void * Mymemmove(void *dst, const void *src, int len){
	char *_src = (char*)src;
	char *_dst = (char*)dst;
	// 检查是否发生重叠且源在目标之前
	if (_dst > _src && _dst < _src + len){
		_dst = _dst + len - 1;
		_src = _src + len - 1;
		while (len--){
			*_dst = *_src;
			_dst--;
			_src--;
		}
	} else {
		while (len--){
			*_dst = *_src;
			_dst++;
			_src++;
		}
	}
	return dst;
}

三、strlen 长度计算的三种实现

第1步:计数器法

使用整型变量逐个遍历直到结束符,适用于基础教学场景。

int Mystrlen(char *str){
	int count = 0;
	while (*str != '\0'){
		str++;
		count++;
	}
	return count;
}

第2步:递归方式

利用递归调用自身,每次减一并加 1,直到遇到 '\0' 返回 0。

int Mystrlen(char *str){
	if (*str == '\0') return 0;
	else return (1 + Mystrlen(str + 1));
}

第3步:双指针相减法

记录起始指针,移动指针直至尾部,两者相减即为长度,效率高且符合 strlen 源码常见实现逻辑。

int Mystrlen(char *str){
	char *p = str;
	while (*p) p++;
	return (p - str);
}

四、字符串复制 strcpy 的实现

strcpy 需要确保目标空间足够大,并在复制完毕后包含 '\0'。以下实现将源内容拷贝至目标并返回目标指针。

char *Mystrcpy(char *dst, const char *src){
	assert(dst != NULL && src !=NULL);
	char *ret = dst;
	while((*dst++ = *src++) != '\0');
	return ret;
}

五、字符串比较 strcmp 的实现

按字典序比较两个字符串,相同返回 0,前者大于后者返回正数,反之返回负数。代码中约定前者大返回 1。

int Mystrcmp(const char* dst, const char *src){
	while (*dst && *src && (*dst == *src)){
		dst++;
		src++;
	}
	if (*dst > *src) return 1;
	else if (*dst < *src) return -1;
	else return 0;
}

六、子串查找 strstr 的实现

在长串 dst 中查找短串 src 首次出现的位置。采用双重循环,外层遍历目标串,内层逐一比对。

char *mystrstr( const char *dst, const char *src){
	assert(dst);
	assert(src);
	const char *p = dst;
	while (*p){
		const char *movep = p;
		const char *sp = src;
		while(*movep && *sp && *sp== *movep){
			sp++;
			movep++;
		}
		if (*sp == '\0') return (char *)p;
		p++;
	}
	return NULL;
}

七、字符串拼接 strcat 的实现

将 src 追加到 dst 末尾,需先找到 dst 的结束符位置再行写入。

char *mystrcat(char*dst, const char*src){
	assert(src);
	assert(dst);
	char*ret = dst;
	while (*dst) dst++;
	while (*src){
		*dst = *src;
		dst++; src++;
	}
	return ret;
}

以上为C语言底层实现常用字符串与内存处理函数的详细内容,更多关于C语言库函数原理的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表