【结丹系列】 内存函数

简介: 内存函数必知必会
内存函数可在任意类型使用,字符串函数只能比较字符串,内存函数不关注’\0’, 只关注要拷贝的字节数

一、memcpy

void * memcpy ( void * destination, const void * source, size_t num )
✔功能演示:参数类型必须是void*。因为memcpy函数是内存拷贝函数,它必须什么类型都能接收。

函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置,这个函数在遇到 '\0' 的时候并不会停下来。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
    int arr1[] = {1,2,3,4,5,6,7,8,9 };
    int arr2[10] = {0};
    memcpy(arr2, arr1, 20);
    for (int i = 0; i < 10; i++) {
        printf("%d", arr2[i]);
    }
    return 0;
}

image-20220713110855860

模拟实现memcpy

✔void 类型不能进行解引用操作和++运算,在解引用操作和++运算之前,要进行强制类型转换。并且因为此函数是一个字节一个字节的拷贝,所以要将ptr1和ptr2变量强制类型转化为char类型
✔目标变量dest的地址需要存放在一个临时指针变量中,因为dest在循环体中一直是变化的
✔将dest和sour指针变量assert断言,使其不为NULL。并且因为sour是不能改变的,所以用const修饰,以保护起来。

image-20220714214420358

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* sour, size_t num){
    assert(dest && sour);
    void* ret = dest;
    while(num--){
        *(char*)dest = *(char*)sour;
        dest = (char*)dest + 1;
        sour  = (char*)sour + 1;
    }
    return ret;
}
int main() {
    int arr1[] = {1,2,3,4,5,6,7,8,9 };
    int arr2[10] = {0};
    my_memcpy(arr2, arr1, 20);
    for (int i = 0; i < 10; i++) {
        printf("%d", arr2[i]);
    }
    return 0;
}

memcpy不支持自身内部拷贝,可能存在覆盖,主要负责拷贝两块独立空间中的数据,重叠内存拷贝使用memmove

二、memmove

void * memmove ( void * destination, const void * source, size_t num )
✔功能实现:如果源空间和目标空间出现重叠,就得使用memmove函数处理
#include<stdio.h>
int main() {
    int arr1[] = { 1,2,3,4,5,6,7,8,9,10};
    int arr2[10] = {0};
    memmove(arr1, arr1+3, 20);
    for (int i = 0; i < 10; i++) {
        printf("%d", arr1[i]);
    }
    return 0;
}

image-20220713164029182

模拟实现memmove

#include<
int main() {
    int arr1[] = {1,2,3,4,5,6,7,8,9,10};
    int arr2[] = {2,3,4,5,6,7,8,9,10};
    my_memmove(arr1, arr1+2, 20);
    my_memmove(arr2+2, arr2, 8);
    for (int i = 0; i < 10; i++) {
        printf("%d", arr1[i]);
    }
    printf("\n");
    for (int i = 0; i < 9; i++) {
        printf("%d", arr2[i]);
    }
    return 0;
}

为避免出现空间重叠现象,根据dest 和 sour 的位置分情况处理,选择从前向后或从后向前拷贝

image-20220714194637865

image-20220714195435369

#include<assert.h>
#include<stdio.h>
void* my_memmove(void* dest, const void* sour, size_t num) {
    assert(dest && sour);
    void* ret = dest;
    if (dest < sour)
    {
    //前向后拷贝
        while (num--) 
        {
            *(char*)dest = *(char*)sour;
            dest = (char*)dest + 1;
            sour = (char*)sour + 1;
        }
    }
    else
    {
    //后向前拷贝
        while (num--)
        {
            *((char*)dest + num) = *((char*)sour + num);
        }
    }
    return ret;
}

三、memcmp


int memcmp ( const void * ptr1, const void * ptr2, size_t num )
✔功能实现:比较两个内存块,将 ptr1 所指向的内存块的前 num 个字节与 ptr2 指向的前num字节数进行比较, 返回不同意义的值
返回值 表明
>0 在两个内存块中不匹配的第一个字节在 ptr1 中的值大于在 ptr2 中的值
0 两个内存块的内容相等
<0 在两个内存块中不匹配的第一个字节在 ptr1 中的值小于在 ptr2 中的值
#include<stdio.h>
#include<string.h>
int main(){
    int arr1[] = { 1,5,4,5 };//01 00 00 00/ 05 00 00 00/ 04 00 00 00 /05 00 00 00
    int arr2[] = { 1,3,5,6 };//01 00 00 00/ 03 00 00 00 /05 00 00 00/ 06 00 00 00
    int ret = memcmp(arr1, arr2, 12);//arr1 > arr2
    printf("%d", ret);
    return 0;
}

image-20220714211211694

模拟实现 memcpy()

✔void 类型不能进行解引用操作和++运算,在解引用操作和++运算之前,要进行强制类型转换。并且因为此函数是一个字节一个字节的拷贝,所以要将ptr1和ptr2变量强制类型转化为char类型
#include<stdio.h>
#include<assert.h>
int my_memcmp(const void* ptr1, const void* ptr2, size_t num) {
    assert(ptr1 && ptr2);
    while (num-- && *(char*)ptr1 == *(char*)ptr2){
              ptr1 = (char*)ptr1 +1;
              ptr2 = (char*)ptr2 +1;
        }
    return(*(char*)ptr1 - *(char*)ptr2);
}
int main(){
    //char arr1[] = "hello world";
    //char arr2[] = "hello bilibili";
    int arr1[] = { 1,5,7,5 };
    int arr2[] = { 1,5,7,6};
    int ret = my_memcmp(arr1, arr2, 12);
    if (ret == 0)
        printf("==\n");
    else if (ret < 0)
        printf("<\n");
    else
        printf(">\n");
    return 0;
}

四、memset()


void * memset ( void * ptr, int value, size_t num );
✔功能实现:将 ptr 所指向的内存块的前num个字节数设置为指定值
#include<stdio.h>
int main() {
    char arr[] = "hello bilibili";
    memset(arr, 'x', 5);
    printf("%s", arr);
    return 0;
}

image-20220714220003032

模拟实现memset()

void* my_memset(void* ptr, int value, size_t num) {
    assert(ptr);
    void* ret = ptr;
    while (num--){
        *(char*)ptr = value;  //赋值
        ptr = (char*)ptr + 1; //q
    }
    return ret;
}
相关文章
|
3月前
10分钟让你学会内存函数:memcpy,memmove,memset,memcmp的用法及模拟实现。
10分钟让你学会内存函数:memcpy,memmove,memset,memcmp的用法及模拟实现。
44 2
|
3月前
|
存储 C语言
C语言学习记录——动态内存函数介绍(malloc、free、calloc、realloc)
C语言学习记录——动态内存函数介绍(malloc、free、calloc、realloc)
68 1
|
3月前
|
C语言
【C语言】:动态内存管理函数malloc,calloc,realloc和free的介绍的介绍
【C语言】:动态内存管理函数malloc,calloc,realloc和free的介绍的介绍
46 0
|
23天前
|
C语言
【C语言篇】字符和字符串以及内存函数详细介绍与模拟实现(下篇)
perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。
|
23天前
|
存储 安全 编译器
【C语言篇】字符和字符串以及内存函数的详细介绍与模拟实现(上篇)
当然可以用scanf和printf输入输出,这里在之前【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)已经讲过了,这里就不再赘述,主要介绍只针对字符的函数.
|
29天前
【C初阶】内存函数:memcpy+memmove+memset+memcmp
【C初阶】内存函数:memcpy+memmove+memset+memcmp
|
2月前
|
存储 缓存 C语言
【C语言】字符函数,字符串函数,内存函数
C语言中的字符串函数和内存函数
31 0
【C语言】字符函数,字符串函数,内存函数
|
3月前
|
C语言
字符串和内存函数(1)
字符串和内存函数(1)
35 7
|
3月前
|
C语言
【C语言】:4大内存函数
【C语言】:4大内存函数
21 2
|
3月前
字符串和内存函数(2)
字符串和内存函数(2)
33 5

热门文章

最新文章