【结丹系列】 内存函数

简介: 内存函数必知必会
内存函数可在任意类型使用,字符串函数只能比较字符串,内存函数不关注’\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;
}
相关文章
|
2月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
42 3
|
26天前
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
58 6
|
2月前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
2月前
|
存储 程序员 编译器
C语言——动态内存管理与内存操作函数
C语言——动态内存管理与内存操作函数
|
2月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
404 1
|
2月前
|
程序员 C语言
C语言内存函数精讲
C语言内存函数精讲
|
2月前
|
存储 编译器 C++
【C++】掌握C++类的六个默认成员函数:实现高效内存管理与对象操作(二)
【C++】掌握C++类的六个默认成员函数:实现高效内存管理与对象操作
|
2月前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
41 0
|
2月前
|
C语言 C++
c语言回顾-内存操作函数
c语言回顾-内存操作函数
48 0
|
2月前
|
存储 C语言 C++
来不及哀悼了,接下来上场的是C语言内存函数memcpy,memmove,memset,memcmp
本文详细介绍了C语言中的四个内存操作函数:memcpy用于无重叠复制,memmove处理重叠内存,memset用于填充特定值,memcmp用于内存区域比较。通过实例展示了它们的用法和注意事项。
83 0

热门文章

最新文章