“从底层到应用:掌握C语言中memcpy、memmove、memset和memcmp函数的使用”

 

目录

1.memcpy函数

2.memmove函数

3.memset函数

4.memcmp函数


简介: 在C语言中,有一些函数被广泛用于处理内存操作。其中,memcpy、memmove、memset和memcmp是四个常用的函数,它们在处理字符串和内存拷贝、移动和比较方面起着重要作用。本文将详细介绍这四个函数的用法,实现和区别,帮助读者更好地理解和使用它们。

  • 1.memcpy函数: memcpy函数用于将源内存区域的内容复制到目标内存区域。其函数原型如下:

void *memcpy(void *dest, const void *src, size_t n);

其中,dest是目标内存区域的指针,src是源内存区域的指针,n是要复制的字节数。该函数返回指向dest的指针。

自定义memcpy函数的实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include <assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(src && dest);

	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

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

	int arr2[20] = { 0 };
	my_memcpy(arr2, arr1, 21);
	int i = 0;
	for (i = 0; i < 20; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}
  • 使用了两个指针变量destsrc来遍历内存区域,并逐字节地将源内存区域的内容复制到目标内存区域。

  • 通过一个循环,遍历num个字节,将src中的内容逐字节复制到dest中,然后将指针destsrc分别向后移动一个字节。

 

  • 2.memmove函数: memmove函数与memcpy函数类似,也用于内存区域的复制,但其处理方式更为安全,能够处理重叠内存区域的拷贝。其函数原型如下:

void *memmove(void *dest, const void *src, size_t n);

与memcpy函数不同的是,memmove函数保证在重叠拷贝时不会出现问题。这是因为memmove会先将源内存区域的内容拷贝到临时区域,然后再将临时区域的内容复制到目标内存区域。

自定义memmove函数的实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include <assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);

	if (dest < src)
	{
		//前->后
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//后->前
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}

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

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

 

通过比较目标地址和源地址的大小,确定是从前向后移动还是从后向前移动。

如果目标地址小于源地址,即从前向后移动,使用一个循环,将源地址的数据逐个复制到目标地址中,并且每次复制后,目标地址和源地址都分别向后移动一个字节。

如果目标地址大于等于源地址,即从后向前移动,同样使用一个循环,从后向前复制数据。

main函数中,定义了一个整型数组arr1,包含了一些整数。

调用my_memmove函数,将arr1+1(即数组的第二个元素地址)开始的20个字节的数据移动到arr1中。然后,通过一个循环输出移动后的arr1数组的元素。

 

  • 3.memset函数: memset函数主要用于将指定的内存区域填充为给定的值。这些值可以是字符、整型数字或其他类型的数据。其函数原型如下:

  • void *memset(void *ptr, int value, size_t num);
    

    其中,ptr是指向要填充的内存区域的指针,value是要填充的值,num是要填充的字节数。该函数返回指向ptr的指针。

    自定义memset函数的实现:

    #include <stdio.h>
    #include <assert.h>
    
    void* my_memset(void* ptr, int value, size_t num) {
        assert(ptr != NULL);
    
        unsigned char* p = (unsigned char*)ptr;
        unsigned char val = (unsigned char)value;
    
        for (size_t i = 0; i < num; i++) {
            p[i] = val;
        }
    
        return ptr;
    }
    
    int main() {
        char str[20] = "Hello World";
    
        my_memset(str, '*', 5);
    
        printf("填充后的字符串为: %s\n", str);
    
        return 0;
    }
    

    在自定义的my_memset函数中,首先使用assert断言来确保传入的指针ptr不为空。

    然后将ptr强制转换为unsigned char指针类型,并将value强制转换为unsigned char类型,以确保按字节进行填充。

    接下来,使用一个循环遍历num次,将value的值复制到ptr指向的内存区域中。

    最后,返回指向ptr的指针。

     

  • 4.memcmp函数: memcmp函数用于比较两个内存区域的内容是否相等。其函数原型如下:

int memcmp(const void *s1, const void *s2, size_t n);

其中,s1和s2是要比较的两个内存区域的指针,n是要比较的字节数。该函数返回一个整数值,表示两个内存区域的比较结果。如果返回值为0,则表示两个内存区域相等;如果返回值小于0,则表示s1小于s2;如果返回值大于0,则表示s1大于s2。

自定义memset函数的实现:

#include <stdio.h>

int my_memcmp(const void* s1, const void* s2, size_t num) {
    const unsigned char* p1 = (const unsigned char*)s1;
    const unsigned char* p2 = (const unsigned char*)s2;

    for (size_t i = 0; i < num; i++) {
        if (p1[i] < p2[i]) {
            return -1;
        } else if (p1[i] > p2[i]) {
            return 1;
        }
    }

    return 0;
}

int main() {
    char str1[] = "Hello";
    char str2[] = "Hello";

    int result = my_memcmp(str1, str2, sizeof(str1));

    if (result == 0) {
        printf("字符串相等\n");
    } else if (result < 0) {
        printf("str1 小于 str2\n");
    } else {
        printf("str1 大于 str2\n");
    }

    return 0;
}

将传入的指针s1和s2都强制转换为const unsigned char类型,以确保按字节进行比较。

接下来,我们使用一个循环遍历num次,逐字节比较两个内存区域的内容。

如果发现p1中的某个字节小于p2中的相应字节,则返回-1表示p1小于p2。

如果发现p1中的某个字节大于p2中的相应字节,则返回1表示p1大于p2。

如果所有字节都相等,则返回0表示两个内存区域相等。

 

 

总结:

  • memcpy函数用于内存的拷贝,是最常用的内存操作函数之一。

  • memmove函数也用于内存的拷贝,但能够处理重叠内存区域的拷贝。

  • memset函数用于将内存区域的每个字节设置为指定的值。

  • memcmp函数用于比较两个内存区域的内容是否相等。

在使用这些函数时,需要注意以下几点:

  • 确保源和目标内存区域的大小合适,避免越界访问。

  • 对于可能存在内存重叠的情况,使用memmove而不是memcpy函数。

  • 确保目标内存区域的大小足够容纳要填充的字节数,避免越界访问。

  • 在对字符数组进行填充时,确保数组末尾有一个空字符(‘\0’)来表示字符串的结束。

  • 比较内存区域时,确保比较的内存大小一致,避免比较超出范围。

通过对memcpy、memmove、memset和memcmp函数的了解,我们可以更高效地处理字符串和内存操作,提高程序的性能和安全性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值