内存及字符串操作memcpy、memmove、strcpy、strcmp等常用标准库函数的实现


之前对于一些标准库函数都是拿来即用,没有考虑过这个函数的优缺点及具体的实现形式,在实习期间,一个标准库函数都是被二次封装了的,还是很有趣的。比如对于malloc函数,内部的形式是void *malloc_s(int ENUM_TYPE, int size),多了一个参数ENUM_TYPE,比如对于我们TM就是MALLOC_TMBUFFER,其原因是因为这样写方便对堆区内存进行统计,防止有的小组malloc空间过大,这样可以及时定位。

本博客将参考Linux常用C函数手册进行标准库函数的一一实现(长期更新)。


1、memcpy实现

/* 标准库中的memcpy是要确保地址不重合
 * 附加说明指针src和dest所指的内存区域不可重叠
 */

/* 实现一:
 * 不考虑内存重叠 */
void *memcpy_s(void *des, void *src, int len)
{
    if (des == NULL || src == NULL) {
        return NULL;
    }
    void *ret = des;
    while (len--)
    {
        *(char *)des = *(char *)src;
        (char *)des++;
        (char *)src++;
    }
    return ret;
}

2、memmove实现

/* 实现二:
/* 考虑内存重叠的情况,此时类似于memmove
 * #include<string.h>
    定义函数
    void *memmove(void *dest,const void *src,size_t n);
    函数说明 : memmove()与memcpy()一样都是用来拷贝src所指的内存内容前n个字节到dest所指的地址上。
    不同的是,当src和dest所指的内存区域重叠时,memmove()仍然可以正确的处理,不过执行效率上会比使用memcpy()略慢些。
    返回值 : 返回指向dest的指针。
    附加说明 :指针src和dest所指的内存区域可以重叠。
 */
void *memmove_s(void *des, const void *src, int len)
{
    void *ret = des;
    if (des == NULL || src == NULL) {
        return NULL;
    }
    if (src < des) {/* 低地址往高地址复制 : 高 -> 高*/
        while (len--) {
            *(char *)(des+len) = *(char *)(src+len);
        }
    } else {
        while (len--)
        {
            *(char *)des = *(char *)src;
            des++;
            src++;
        }
    }
    return ret;
}

 

3、strcmp实现

/* strcmp_s实现 */
int strcmp_s(char *str1, char *str2)
{
    int ret = 0;
    if (str1 == NULL || str2 == NULL) {
        return -1;
    }
    while ((*(str1) != ' ') && (*(str2) != ' ') && (*(str1) == *(str2))) {
        str1++;
        str2++;
        printf("*str1 = %c\n", *(str1));
    }
    ret = *(str1) - *(str2);
    return ret;
}

 

4、strcpy实现

/* strcpy_s 实现 */
char *strcpy_s(char *des, char *src)
{
    char *ret = des;
    if ((des == NULL) || (src == NULL)) {
        return NULL;
    }
    while (*(src) != '\0')
    {
        *(des) = *(src);
        des++;
        src++;
    }
    *(src) = '\0';
    return ret;
}

5、strlen实现

sizeof和strlen的区别:

strlen( )计算字符串的长度,以'\0'为字符串结束标志。

sizeof( )是分配的数组实际所占的内存空间大小,不受里面存储内容。

sizeof( )是运算符,由于在编译时计算,因此sizeof( )不能用来返回动态分配的内存空间的大小。实际上,用sizeof( )来返回类型以及静态分配的对象、结构或数组的空间,返回值跟这些里面所存储的内容没有关系。

具体而言,当参数分别如下时,sizeof返回的值含义如下:

数组 -- 编译时分配的数组空间大小

指针 -- 存储该指针所用的空间大小

类型 -- 该类型所占的空间的大小

对象 -- 对象的实际占用空间大小

函数 -- 函数返回类型所占空间的大小

strlen()是函数,可以计算字符串的长度,直到遇到结束符NULL才结束,返回的长度大小不包含NULL。

ubuntu@VM-0-4-ubuntu:~/share/codeForTest$ ./10-08 
sizeof(str1) = 8
strlen(str1) = 7
sizeof(str2) = 20
strlen(str2) = 7
ubuntu@VM-0-4-ubuntu:~/share/codeForTest$ cat 10-08.c 
#include "stdio.h"

int main()
{
    char *str1 = "absdefg";
    char str2[20] = "abcdefg";
    printf("sizeof(str1) = %d\n", sizeof(str1));
    printf("strlen(str1) = %d\n", strlen(str1));
    printf("sizeof(str2) = %d\n", sizeof(str2));
    printf("strlen(str2) = %d\n", strlen(str2));
    return 0;
}

 

unsigned int strlen_s(char *str)
{
    if (str == NULL) {
        return 0;
    }
    unsigned int len = 0;
    while (*str != '\0') {
        len++;
        str++;
    }
    return len;
}

6、atoi的实现

int atoi_s(char *src)
{
    if (src == NULL) {
        return 0;
    }
    while (*src == ' ') {
        src++;
    }

    int signalFlag = 1;
    int ans = 0;
    if (*src == '-') {
        signalFlag = -1;
    }
    if (*src == '-' || *src == '+') {
        src++;
    }
    while (*src > '0' && *src <= '9')
    {
        ans = ans * 10 + *src - '0';
        src++;
    }
    ans *= signalFlag;
    
    return ans;
}

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值