【C语言】内存操作函数

本文详细介绍了C语言中的四个内存操作函数:memcpy用于无重叠复制,memmove处理重叠内存,memset用于填充固定值,memcmp用于字节比较。通过模拟实现和实例演示了它们的用法和特点。
摘要由CSDN通过智能技术生成

在这里插入图片描述

前言
C语言提供了一些内存操作函数,这些函数允许你在内存中执行各种操作,如复制、设置、比较等。与处理字符串函数不同的是,内存处理函数可对多种类型进行处理。接下来我们讲解并模拟实现这些函数。


1、memcpy的使用

描述
C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1。

声明

void *memcpy(void *str1, const void *str2, size_t n)

参数
str1 – 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
str2 – 指向要复制的数据源,类型强制转换为 void* 指针。
n – 要被复制的字节数。

返回值
该函数返回一个指向目标存储区 str1 的指针。

使用实例:

// 将字符串复制到数组 dest 中
#include <stdio.h>
#include <string.h>
 
int main ()
{
   const char src[50] = "hello world";
   char dest[50];
 
   memcpy(dest, src, strlen(src)+1);
   printf("dest = %s\n", dest);
   
   return(0);
}

运行结果:
在这里插入图片描述


1.1 memcpy的模拟实现

void* memcpy(void* dst, const void* src, size_t count)
{
	void* ret = dst;
	assert(dst);
	assert(src);
	
	while (count--) {
	     
	     //*(char*)dst++ = *(char*)src++这种写法是未定义的,在某些编译是不允许的
		*(char*)dst = *(char*)src;
		dst = (char*)dst + 1;
		src = (char*)src + 1;
	}
	return ret;
}

2、memmove的使用

描述
C 库函数 void *memmove(void *str1, const void *str2, size_t n) 从 str2 复制 n 个字符到 str1,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。 如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。

声明

void *memmove(void *str1, const void *str2, size_t n)

参数
str1 – 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
str2 – 指向要复制的数据源,类型强制转换为 void* 指针。
n – 要被复制的字节数。

返回值
该函数返回一个指向目标存储区 str1 的指针。

使用实例

#include <stdio.h>
#include <string.h>

int main()
{
	const char dest[] = "oldstring";
	
	printf("old dest = %s\n", dest);
	memmove(dest+2, dest, 5);
	printf("new dest = %s\n", dest);

	return(0);
}

运行结果
在这里插入图片描述


2.1 memmove的模拟实现

void* my_memmove(void* dst, const void* src, size_t count)
{
    // 保存目标地址的指针,以便后面返回
    void* ret = dst;
    
    // 如果目标地址在源地址之后,或者它们没有重叠的部分
    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;
}

3、memset的使用

描述
C 库函数 void *memset(void *str, int c, size_t n) 复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。

声明

void *memset(void *str, int c, size_t n)

参数
str – 指向要填充的内存块。
c – 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
n – 要被设置为该值的字符数。

返回值
该值返回一个指向存储区 str 的指针。

实例

#include <stdio.h>
#include <string.h>

int main()
{
	char str[50]="hello world";

	memset(str, '$', 7);
	puts(str);

	return 0;
}

运行结果
在这里插入图片描述


3.1 memset的模拟实现

void* my_memset(void* ptr, int value, size_t num) {
    unsigned char* byte_ptr = (unsigned char*)ptr;
    // 将value强制转换为unsigned char类型以确保正确设置每个字节
    unsigned char byte_value = (unsigned char)value;
    
    for (size_t i = 0; i < num; i++) {
        *byte_ptr = byte_value;
        byte_ptr++;
    }
    
    return ptr;
}

4、memcmp的使用

描述
C 库函数 int memcmp(const void *str1, const void *str2, size_t n)) 把存储区 str1 和存储区 str2 的前 n 个字节进行比较。

声明

int memcmp(const void *str1, const void *str2, size_t n)

参数
str1 – 指向内存块的指针。
str2 – 指向内存块的指针。
n – 要被比较的字节数。

返回值
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str1 大于 str2。
如果返回值 = 0,则表示 str1 等于 str2。

实例

#include <stdio.h>
#include <string.h>

int main ()
{
   char str1[15];
   char str2[15];
   int ret;

   memcpy(str1, "abcdef", 6);
   memcpy(str2, "ABCDEF", 6);

   ret = memcmp(str1, str2, 5);

   if(ret > 0)
   {
      printf("str2 小于 str1");
   }
   else if(ret < 0) 
   {
      printf("str1 小于 str2");
   }
   else 
   {
      printf("str1 等于 str2");
   }
   
   return(0);
}

运行结果
在这里插入图片描述


4.1 memcmp的模拟实现

int my_memcmp(const void* ptr1, const void* ptr2, size_t num) {
    
    const unsigned char* byte_ptr1 = (const unsigned char*)ptr1;
    const unsigned char* byte_ptr2 = (const unsigned char*)ptr2;
    
    for (size_t i = 0; i < num; i++) {
        if (*byte_ptr1 != *byte_ptr2) {
            // 如果发现不相等的字节,返回它们的差值
            return (*byte_ptr1 - *byte_ptr2);
        }
        byte_ptr1++;
        byte_ptr2++;
    }
    
    // 如果没有找到不相等的字节,返回0表示相等
    return 0;
}

以上函数均包含在C的标准库—<string.h>
信息来源:C语言标准库–<string.h>


在这里插入图片描述
如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值