当前位置: 首页 > news >正文

C语言内存函数

文章目录

  • 1. memcpy函数
    • 1.1使用规则
    • 1.2memcpy函数的模拟实现
  • 2.memmove函数
    • 2.1使用规则
    • 2.2memmove函数的模拟实现
  • 3.memset函数
  • 4.memcmp函数

1. memcpy函数

1.1使用规则

void *memcpy ( void *destination, const void *source, size_t num );
  • 将source指向的源内存区域中指定字节数(num)的数据复制到destination指向的目标内存区域
  • 遇 ‘\0’ 不会停下
  • 源内存区域和目标内存区域有重叠可能产生未定义行为
    • 当源内存区域和目标内存区域有重叠时,建议使用 memmove 函数,它可以正确处理内存重叠的情况
#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 类型通常占 4 个字节,所以 20 字节相当于 5 个 int 元素
	// 因此这里将 arr1 的前 5 个元素复制到 arr2 的前 5 个位置

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

在这里插入图片描述

1.2memcpy函数的模拟实现

#include <stdio.h>
#include <assert.h>

// 参数 dst 是目标内存区域的起始地址
// 参数 src 是源内存区域的起始地址
// 参数 count 是要复制的字节数
void* memcpy(void* dst, const void* src, size_t count)
{
    void* ret = dst;

    assert(dst);
    assert(src);

    /* 从低地址向高地址复制数据 */
    while (count--) 
    {
        *(char*)dst = *(char*)src;
        dst = (char*)dst + 1;
        src = (char*)src + 1;
    }

    return(ret);
}

int main() 
{
    int arr1[] = { 1, 2, 3, 4, 5 };
    int arr2[5];

    memcpy(arr2, arr1, sizeof(arr1));

    for (int i = 0; i < 5; i++) 
    {
        printf("%d ", arr2[i]);
    }
    printf("\n");

    return 0;
}

在这里插入图片描述

2.memmove函数

2.1使用规则

当源内存区域和目标内存区域有重叠时,建议使用 memmove 函数

void *memmove ( void *destination, const void *source, size_t num );
#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);
	// arr1 的前 5 个元素复制到 arr1 的第 3 个位置开始往后的 5 个位置

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

在这里插入图片描述

2.2memmove函数的模拟实现

#include <stdio.h>
#include <assert.h>

void* memmove(void* dst, const void* src, size_t count)
{
    void* ret = dst;

    assert(dst != NULL);
    assert(src != NULL);

    // 情况一:目标内存区域在源内存区域之前,或者目标内存区域在源内存区域之后且不重叠
    if (dst <= src || (char*)dst >= ((char*)src + count)) 
    {
        /* 从低地址向高地址复制数据 */
        while (count--) 
        {
            *(char*)dst = *(char*)src;
            dst = (char*)dst + 1;
            src = (char*)src + 1;
        }
    }
    // 情况二:目标内存区域和源内存区域存在重叠,且目标内存区域在源内存区域之后
    else 
    {
        /* 从高地址向低地址复制数据 */

        // 将目标内存地址移动到要复制的最后一个字节的位置
        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);
}

int main() 
{
    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    
    memmove(arr + 2, arr, 20);

    for (int i = 0; i < 10; i++) 
    {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

3.memset函数

memset 函数用于将指定内存区域的前若干个字节设置为指定的值,常用于初始化内存或清空内存。

void *memset ( void *ptr, int value, size_t num );
#include <stdio.h>
#include <string.h>

int main()
{
	char str[] = "hello world";
	memset(str, 'x', 6);   // 将str数组的前 6 个字节填充为字符 'x'
	printf("%s", str);
	return 0;
}

在这里插入图片描述

4.memcmp函数

int memcmp ( const void *ptr1, const void *ptr2, size_t num );
  • 比较ptr1和ptr2指针指向的位置开始,向后的num个字节
  • 根据比较结果返回小于、等于或大于 0 的整数,以此判断两个内存区域内容的大小关系
  • 直到比较完 num 个字节或发现不同
#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' is greater than '%s'.\n", buffer1, buffer2);
	else if (n < 0)
		printf("'%s' is less than '%s'.\n", buffer1, buffer2);
	else
		printf("'%s' is the same as '%s'.\n", buffer1, buffer2);

	return 0;
}

在这里插入图片描述

相关文章:

  • 【MATLAB例程】RSSI/PLE定位与卡尔曼滤波NLOS抑制算法,附完整代码
  • 智能自动化新纪元:AI与UiPath RPA的协同应用场景与技术实践
  • vscode软件中引入vant组件
  • leetcode hot100-34 合并K个升序链表
  • 什么是Firehose?它的作用是什么?
  • 蓝桥杯笔记——递归递推
  • FTP 实验(ENSP模拟器实现)
  • 力扣-贪心-53 最大子数组和
  • LeetCode刷题---二分查找---287
  • Java 大视界 -- Java 大数据未来十年的技术蓝图与发展愿景(95)
  • DeepSeek+Cherry Studio实现本地私有满血版
  • 企业微信第三方应用开发025_企微通讯录组件使用04_vue中使用ww-open-data通讯录展示组件---企业微信开发027
  • 《深度剖析:AI与姿态估计技术在元宇宙VR交互中的应用困境》
  • 记录Unity一个奇妙bug
  • Spring有哪些缺点?
  • Redis存储⑪主从复制_分布式系统解决单点问题
  • verilog笔记
  • PHP Libxml:深入解析XML解析库及其在PHP中的应用
  • strcpy与strncpy作为复制函数的用法与区别
  • 洛谷 P1102 A-B 数对(详解)c++
  • 招行:拟出资150亿元全资发起设立金融资产投资公司
  • 洞天寻隐·学林纪丨玉洞桃源:仇英青绿山水画中的洞天与身体
  • 现场|万米云端,遇见上博
  • 大学2025丨专访清华教授沈阳:建议年轻人每天投入4小时以上与AI互动
  • 中国首位、亚洲首位!赵心童夺得斯诺克世锦赛冠军
  • 国产基因测序仪龙头华大智造业绩持续承压,今年有望迎来拐点?