C语言内存函数

 

前言:

Hello各位小伙伴们,上期我们介绍了C语言的字符串函数的使用和模拟,这期我们来介绍一下C语言内存函数。

C语言的内存函数与字符串不同的是前者不在考虑类型,直接把这块的内存进行处理,不在有字符这一限制。所以处理的内容类型不同所以指针类型是void*类型。这里具体介绍一下memcpy,memmove,还有memset的使用和模拟实现。

 memcpy的使用和模拟实现

void * memcpy ( void * destination, const void * source, size_t num );

与strncpy相比十分类似,只不过指针类型为void*,因为拷贝的内容无法确定类型,所以使用void*。返回类型仍为destination is returned.

• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存置。​
• 这个函数在遇到 '\0' 的时候并不会停下来。
• 如果source和destination有任何的重叠,复制的结果都是未定义的。​

 同时要注意的是在memcpy,memmove,还有memset中的单位都是字节。memcpy在拷贝的过程中都是以字节为单位进行拷贝。

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

int main ()
{
    int arr1[] = { 1,2,3,4 };
    int arr2[5] = { 0 };
    memcpy(arr2,arr1,3*sizeof(int))
    for(int i = 0;i < 5;i++)
    {
        printf("%d ",arr2[i]);
    }
}

要注意的是由于memcpy的单位是字节,所以在确定拷贝元素个数的时候,要以字节为单位。如果要拷贝3个整数,则需要在size_t 处写成12及3*sizeof((int))。

模拟实现:

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	while(num--)
	{
		*(char*)dest = *(char*)src;//强置类型转化是临时的
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

int main()
{
	int arr1[6] = { 0 };
	int arr2[] = { 1,2,3,4,5 };
	my_memcpy(arr1, arr2, 4 * sizeof(int));
	for (int i = 0; i < 6; i++)
	{
		printf("%d ", arr1[i]);
	}

	return 0;
}

因为单位是字节所以在强制类型转化的时候转化成char*类型,char*一次访问一个字节。

同时值得注意的是memcpy是在拷贝不会重合的情况下使用,但在拷贝重合时在VS上仍然适用但最好使用memmove。

 memmove的使用和模拟实现

memmove是在出现重叠的情况下使用。

void * memmove ( void * destination, const void * source, size_t num );

#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	memmove(arr + 2, arr, 4 * sizeof(int));
	for (int i = 0; i < 9; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}//1 2 1 2 3 4 7 8 9

模拟实现:(在出现重叠的情况下)

现在我们分析一下该过程在上述代码中我们只考虑了一种情况就是dest在src的前面:

此时在进行拷贝的时候从src的第一位向dest的第一位进行拷贝,及从前向后拷贝

另一种情况是src在dest的前面:

 

此时在进行拷贝的时候从src的最后一位向dest的最后一位进行拷贝,及从后向前拷贝

代码展示:

#include<stdio.h>
void*my_memmove(void*dest, void*src, size_t num)
{
    //从前向后拷贝
    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);
        }
    }
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	my_memmove(arr + 2, arr, 4 * sizeof(int));
	for (int i = 0; i < 9; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

当dest和src不出现重叠情况的时候,上述模拟同样满足,小伙伴们可以自行尝试一下。

memset的使用和模拟实现

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

memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。

一般情况下我们想要将一个数组元素进行修改的话,需要使用for循环进行一个数组的遍历。例如:

#include<stdio.h>
int main ()
{
    int i = 0;
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 } //将数组元素修改为7
    for(i = 0;i < 10;i++)
    {
        arr[i] = 7;
    }
    //打印数组
    .........
    return 0;
}

​此时我们可以使用memset进行一个数组元素的修改

#include<stdio.h>
#include<string.h>
int main ()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    memset(arr,0,4*sizeof(int));
    for(int i = 0;i < 10;i++)
    {
        printf("%d ",arr[i]);
    }
}//0 0 0 0 5 6 7 8 9 10

同时值得注意的是int value,size_t num 单位都是字节

同时memset还可以设置字符数组:

#include<stdio.h>
#include<string.h>
int main ()
{
    char arr[] = "Good morning ";
    memset(arr,'*',4);
    printf("%s",arr);
}

此时就不在特殊考虑单位是字节的问题,因为sizeof(char)为1。

模拟实现:

#include<stdio.h>
#include<assert.h>
void*my_memset(void*dest,char str,size_t num)
{
    assert(dest);
    void *ret = dest;
    while(num--)
    {
        *(char*)dest = str;
        dest = (char*)dest + 1;
    }  
    return ret;  
}
int main ()
{
    char arr[] = "Good morning";
    my_memset(arr,'*',4);
    printf("%s",arr);
}

memcmp的使用和模拟实现

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

• 比较从ptr1和ptr2指针指向的位置开始,向后的num个字节​
• 返回值如下:

Return Value:

Returns an integral value indicating the relationship between the content of the memory blocks:

return valueindicates
<0the first byte that does not match in both memory blocks has a lower value in ptr1 than in ptr2 (if evaluated as unsigned char values)
0the contents of both memory blocks are equal
>0the first byte that does not match in both memory blocks has a greater value in ptr1 than in ptr2 (if evaluated as unsigned char values)

 和strcmp不同的是,memcmp比较的是内存块中字节的个数。

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8 };
	int arr2[] = { 1,2,3,3 };
	//1----在内存中的存储倒着存放:01 00 00 00
	int ret = memcmp(arr1, arr2, 12);
	printf("%d", ret);
	return 0;
}

模拟实现就靠各位小伙伴自己动手尝试吧,我们下期再见。

  • 18
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值