C语言从入门到进阶——第18讲:内存函数

文章目录

  • [1. memcpy](#1. memcpy)
  • [2. memmove](#2. memmove)
  • [3. memset](#3. memset)
  • [4. memcmp](#4. memcmp)

1. memcpy

函数原型

c 复制代码
void * memcpy ( void * destination, const void * source, size_t num );

功能

  • memcpy是完成内存块拷贝的,不关注内存中存放的数据是啥
  • 函数memcpysource的位置开始向后复制num个字节的数据到destination 指向的内存位置。
  • 如果sourcedestination有任何的重叠,复制的结果都是未定义的。
    • 内存重叠的情况使用memmove就行
  • memcpy 的使用需要包含<string.h>

参数

  • destination:指针,指向目标空间,拷贝的数据存放在这里
  • source:指针,指向源空间,要拷贝的数据从这里来
  • num:要拷贝的数据占据的字节数

返回值

拷贝完成后,返回目标空间的起始地址

代码演示

c 复制代码
#include <stdio.h>
#include <string.h>

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

模拟实现

c 复制代码
void * memcpy ( void * dst, const void * src, size_t count)
{
    void * ret = dst;
    assert(dst);
    assert(src);

    // copy from lower addresses to higher addresses
    while (count--) {
        *(char *)dst = *(char *)src;
        dst = (char *)dst + 1;
        src = (char *)src + 1;
    }
    return(ret);
}

2. memmove

函数原型

c 复制代码
void * memmove ( void * destination, const void * source, size_t num );

功能

  • memmove函数也是完成内存块拷贝的
  • memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • memmove的使用需要包含<string.h>

参数

  • destination:指针,指向目标空间,拷贝的数据存放在这里
  • source:指针,指向源空间,要拷贝的数据从这里来
  • num:要拷贝的数据占据的字节数

返回值

拷贝完成后,返回目标空间的起始地址

代码演示

c 复制代码
#include <stdio.h>
#include <string.h>

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

输出的结果

复制代码
1 1 2 3 4 5 6 7 8 9 10

模拟实现

c 复制代码
void * memmove ( void * dst, const void * src, size_t count)
{
    void * ret = dst;
    if (dst <= src || (char *)dst >= ((char *)src + count)) {
        // Non-Overlapping Buffers
        // copy from lower addresses to higher addresses
        while (count--) {
            *(char *)dst = *(char *)src;
            dst = (char *)dst + 1;
            src = (char *)src + 1;
        }
    }
    else {
        // Overlapping Buffers
        // copy from higher addresses to lower addresses
        dst = (char *)dst + count - 1;
        src = (char *)src + count - 1;

        while (count--) {
            *(char *)dst = *(char *)src;
            dst = (char *)dst - 1;
            src = (char *)src - 1;
        }
    }
    return(ret);
}

3. memset

函数原型

c 复制代码
void * memset ( void * ptr, int value, size_t num );

功能

  • memset函数是用来设置内存块的内容的,将内存中指定长度的空间设置为特定的内容。
  • memset的使用需要包含<string.h>

参数

  • ptr:指针,指向要设置的内存空间,也就是存放了要设置的内存空间的起始地址。
  • value:要设置的值,函数将会把value值转换成unsigned char的数据进行设置的。也就是以字节为单位来设置内存块的。
  • num:要设置的内存长度,单位是字节。

返回值

返回的是要设置的内存空间的起始地址。

代码演示

c 复制代码
#include <stdio.h>
#include <string.h>
int main () {
    char str[] = "hello world";
    memset (str,'x',6);
    printf(str);
    return 0;
}

输出的结果

复制代码
xxxxxxworld

总结

当有一块内存空间需要设置内容的时候,就可以使用memset函数,值得注意的是memset函数对内存单元的设置是以字节为单位的。

4. memcmp

函数原型

c 复制代码
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

功能

比较指定的两块内存块的内容,比较从ptr1ptr2指针指向的位置开始,向后的num个字节
memcmp的使用需要包含<string.h>

参数

  • ptr1:指针,指向一块待比较的内存块
  • ptr2:指针,指向另外一块待比较的内存块
  • num:指定的比较长度,单位是字节

返回值

返回值 含义
>0 ptr1内存块数据大于ptr2(以unsigned char值比较)
=0 ptr1与ptr2内存块数据相等
<0 ptr1内存块数据小于ptr2(以unsigned char值比较)

代码演示

c 复制代码
#include <stdio.h>
#include <string.h>

int main()
{
    char buffer1[] = "DWgaOtP12df0";
    char buffer2[] = "DWGAOTP12DF0";
    int n;
    n = memcmp(buffer1, buffer2, sizeof(buffer1));

    if (n > 0) 
        printf("'%s' 大于 '%s'.\n", buffer1, buffer2);
    else if (n < 0) 
        printf("'%s' 小于 '%s'.\n", buffer1, buffer2);
    else
        printf("'%s' 和 '%s' 一样.\n", buffer1, buffer2);

    return 0;
}

总结

如果要比较2块内存单元的数据的大小,可以使用memcmp函数,这个函数的特点就是可以指定比较长度。
memcmp函数是通过返回值告知大小关系的。

相关推荐
geovindu1 天前
go: Flyweight Pattern
开发语言·设计模式·golang·享元模式
xyq20241 天前
TypeScript中的String类型详解
开发语言
小糖学代码1 天前
LLM系列:1.python入门:15.JSON 数据处理与操作
开发语言·python·json·aigc
handler011 天前
从源码到二进制:深度拆解 Linux 下 C 程序的编译与链接全流程
linux·c语言·开发语言·c++·笔记·学习
小白学大数据1 天前
现代Python爬虫开发范式:基于Asyncio的高可用架构实战
开发语言·爬虫·python·架构
渔舟小调1 天前
P19 | 前端加密通信层 pikachuNetwork.js 完整实现
开发语言·前端·javascript
不爱吃炸鸡柳1 天前
数据结构精讲:树 → 二叉树 → 堆 从入门到实战
开发语言·数据结构
网络安全许木1 天前
自学渗透测试第21天(基础命令复盘与DVWA熟悉)
开发语言·网络安全·渗透测试·php
t***5441 天前
如何在Dev-C++中使用Clang编译器
开发语言·c++