长沙市网站建设_网站建设公司_MySQL_seo优化
2025/12/19 22:08:54 网站建设 项目流程

一.strlen实现

str的原理:它的作用是计算字符串长度,根据这个知识我们来写代码吧。

int MyStrlen(const char* s)
{int count = 0;//用于计算长度while(*s != '\0'){count++;s++;}return count;
}

其实strlen的模仿是比较简单的,只要死抓strlen是以'\0'结尾的即可,下面我用图带着大家理解一下吧。

其实就是这样的,s每次++其实就是往上移动一格,直到碰到'/0'才会停止,我们就轻松搞定了strlen的模拟实现。

二.strcpy

  strcpy的原理:将源字符串 src(包括结束符 '\0')复制到目标地址 dest 指向的内存空间中。

strcpy(char* dest,char* src)

根据strcpy的定义其实也能清楚它到底要干嘛,将src拷到dest你可以理成把src的字符一个一个拷到dest即可。

        下面我们就来实现它吧!

char* strcpy(char* des, const char* src)
{assert(des != NULL);//看是不是NULLassert(src != NULL);char* str = des;//保留des用于返回while (*src != '\0'){*str = *src;str++;src++;}*str = '\0';return des;
}

        但是这个代码其实是有槽点的很且很不安全,下面我们用图来分析这个槽点是什么
    你发现了没,如果真的要把src内容全部塞给dest那么就会导致dest访问越界,这也C语言中strcpy的一个安全隐患

三.strcmp

strcmp的原理:按字典顺序依次比较两个字符串的字符大小(即:从第一个字符开始依次往下比)前者大返回一个任意整数(我将用1代替)相等返回0,后者大返回任意一个负数(我用-1代替)

int strcmp(const char* str1, const char* str2)
{assert(str1);assert(str2);const char* s1 = str1;const char* s2 = str2;while (*s1 != '\0' && *s2 != '\0'){if (*s1 > *s2){return 1;}else if (*s1 < *s2){return -1;}else{s1++;s2++;}}if (*s1 == '\0' && *s2 =='\0'){return 0;}else if (*s1 != '\0'){return 1;}else{return -1;}
}

循环终止时,结果只能是1或-1,因为此时字符比较已出现差异。若循环未终止,则存在三种可能情况:前者字符串到达终止符'\0'、后者字符串到达'\0',或双方同时到达'\0'。

四.strstr

strstr的原理:在一个字符串(主串)中找另一个字符串(子串)首次出现的位置

char* strstr(const char* str1, const char* str2)
{assert(str1 != NULL);assert(str2 != NULL);if (!*str2)return((char*)str1);//这里强转是因为C的一个特殊的情况,就是参数是const char*返回的确实char*const char* cp = str1;const char* s1, * s2;while (*cp){s1 = cp;s2 = str2;while (*s1 == *s2 && *s2 != '\0'){s1++;s2++;}if(*s2 == '\0' )return (char*)cp;cp++;}return(NULL);
}

防止野指针与空字符串处理
assert用于确保str1str2非空指针,避免野指针问题。若str2为空字符串,直接返回str1,因为空串是任何字符串的子串。

循环核心逻辑
外层循环通过cp遍历str1的每个字符作为匹配起点。内层循环通过s1s2同步移动比较字符,若完全匹配(*s2 == '\0'),则返回当前cp的位置。若中途不匹配,则外层循环跳到下一个字符重新开始匹配。

可优化点说明

  1. 循环边界优化
    外层循环可限制为strlen(str1) >= strlen(str2)的情况,避免无效比较。例如str1="ab"str2="abc"无需比较。

  2. 两层循环的必要性
    str1="bbac"str2="bac"为例:

  • 第一次从str1的第一个'b'开始匹配,内层比较到第二个字符'b' != 'a'失败。
  • 外层循环跳到第二个'b'重新匹配,此时内层完整匹配"bac",返回正确结果。
  1. 终止条件*s2 != '\0'的作用
    防止比较越界。例如str1="abc\0xxx"str2="abc",当s2指向'\0'时匹配成功,若未检查可能导致s1s2继续向后访问,引发越界。

五.memcpy

memcpy的原理:其核心是按字节,逐个复制内存数据,不关心数据的类型(因此是 “内存拷贝”)

//des:目的地,src:来源,count:拷贝几个字节
void* memcpy1(void* dst, const void* src, size_t count)
{assert(dst);assert(src);char* s1 = (char*)dst;char* s2 = (const char*)src;while (count--){*s1 = *s2;s1++;s2++;}return dst;
}

其实memcpy和strcpy原理都是差不多的,不过memcpy要实现的是任意类型,而strcpy只能实现字符类型,其实要理解这个代码只需要认识内存即可,下面我通过一张图来展示

        这里我们以整数类型为例(int n = 4)。整数类型在内存中占4个字节空间,其地址取最低位的那个字节地址。只要保证这4个字节空间连续存储即可。接下来我们重点讨论内存移动的问题。

        为什么使用void指针?可以将其理解为无类型属性(就像五行中的"无"),而其他类型都有特定属性(金、木、水、火、土)。要实现所有类型的拷贝,就需要一个能承载各种类型的通用载体,void*(无类型)显然是最合适的选择。

        但为什么又要转为char类型呢?因为void*不能直接解引用操作,只能作为载体使用。选择char类型是因为:char类型大小为1字节,因此char指针每次移动1字节这样就能确保精确控制内存移动。如果使用short(每次移动2字节),就无法正确处理char类型数据(1字节),会导致产生垃圾数据。        

        理解了这些,memcpy的工作原理就清晰了。相信聪明的你已经明白了其中的原理。

        但是这个代码是可能有问题的,至于什么问题下面我用图来展示。

你看第一张图是符合memcpy(不会出现问题)但是你看第二张图很明显出了问题,为什么呢?

其实我们根据代码可以知道,我们是用src取赋值给dst,但是如果你dst在src前面就会导致一个问题,我src把第一格的内容给了dst(src下一格)那么我在取下一格不就是src上一格的内容吗,因此就会导致问题,而这个问题就叫内存重叠。

        我们知道了memcpy当dst在src前面的时候会出现内存重叠,但是在前面多少不会出现内存重叠呢?

        其实就是保证dst不会触碰到src的地址,即dst起点>src终点。

六.memmove

memmove的出现就是为了解决内存重叠的问题的

void* memmove(void* dst, const void* src, size_t count)
{void* ret = dst;char* dst1 = (char*)dst;const char* src1 = (const char*)src;if (dst1 < src1 || dst1 > src1 + count)//确保元素修改后不在使用{while (count--){*dst1 = *src1;dst1 ++;src1 ++;}}else{dst1 = dst1 + count - 1;src1 = src1 + count - 1;while (count--){*dst1 = *src1;dst1 --;src1 --;}}return ret;
}

 从代码中可以看出,memmove 的解决方案体现在 else 语句块中。让我们分析这段代码的具体作用吧。

        memcpy 之所以会出现内存重叠问题,是因为 src 可能将自身资源复制到 src+n 的位置。这样后续操作时,src 可能会再次访问这个位置。要解决这个问题,关键在于避免 src 将资源复制到自己将要访问的位置。

        解决方案很简单:让 src 把已复制的内容全部放在目标位置之后。这样就能确保 src 不会重复处理同一个内容。

这次我讲的是面试高频率考的函数实现,希望能给大家带来帮助,如果有误可以评论我,我们抓紧修改的,希望能大家一起进步,我的一些解释采用了AI润色,希望和它的帮助下能给大家带来简洁明了的解释

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询