我是靠谱客的博主 眯眯眼秀发,最近开发中收集的这篇文章主要介绍c语言,内存操作函数的秘密,空类型指针含义 memcpy,memmove,memset 解析与自主实现,内附完整代码。,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在初学编程语言时,赋值语句一向被使用的很频繁,其实赋值语句就是内存函数的基本逻辑

下面我们来看一个简单赋值语句的例子:

int main()
{
    int a = 1;
    int b = 0;
    int c = 0;

    b = a;
    char* pa = (char*)&a;
    char* pc = (char*)&c;
    printf("%d %dn", b, c);
    for (int i = 0; i < 4; i++)
    {
        *(pc + i) = *(pa + i);
    }
    printf("%d %dn", b, c);
    return 0;
}

对于同类型变量的数据进行交换时,我们可以直接赋值 b = a;

也可以将其交给指针,在对其地址进行强制类型转换后,一个字节一个字节的进行交换。

    char* pa = (char*)&a;
    char* pc = (char*)&c;
    for (int i = 0; i < 4; i++)
    {
        *(pc + i) = *(pa + i);
    }

   for (int i = 0; i < 4; i++)

//整形变量总共四个字节,所以这里循环的交换四次,也就交换了四个字节,正好是一个整形的大小。

我们来编译看一下结果:

可以看到,直接赋值,和每个字节按顺序赋值达到的效果是相同的。 

空类型指针的作用:

 在上面的例子可以看到,将int 类型的变量取地址交给char类型的指针,虽然没有错误(因为不同变量地址的大小都是一样,不同类型指针的字节大小也是相同的)所以只是赋值的话,是可以编译的过去的。但是可以看到,编译的结果有一个警告,类型不兼容。而void类型的指针来接收int类型变量的地址时,是没有警告的。

void类型的指针,可以接受任意类型变量的地址,因为他没有具体的类型,但是他也因为没有具体类型从而不能直接进行解引用。(因为指针在没有类型的情况下,解引用不知道该访问几个字节的空间)

内存拷贝函数:memcpy();

定义形式:void *memcpy( void *dest, const void *src, size_t count );

void *dest:接收目的空间首地址的指针

const void *src:接收源空间首地址的指针

size_t count :所需要拷贝的字节个数

自主实现如下:

 完整代码如下:

void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	for (int i = 0; i < num; i++)
	{
		*((char*)dest + i) = *((char*)src + i);
	}
	return dest;
}
int main()
{
	int arr1[20] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

我们以空类型的指针进行接受,然后将其强制类型转换成char类型的变量进行操作。再知道num(需要交换的字节个数),就可以对其进行一个字节一个字节的交换。

但是这个函数有一个缺点就是不能拷贝内存重叠情况的数据,我们来看下面一个例子

将数组arr1中前五个字节的变量(1,2,3,4,5)拷贝到arr1+2的位置上(3,4,5,6,7)

可以看到,得到的结果和我们不是我们想看到的,因为我们是从前到后的数据赋值,这样的话,因为有内存重叠的情况,所以前面赋值的数据会把后面需要复制的数据进行覆盖

 示意图如下:

所以这里就需要引入另一个函数了

memmove();

我们再来看这样的一个例子 :

将src指向的五个整形空间的数据赋值到dest指向的五个整形空间

如果我们从后向前的赋值,这样就能很好的规避后面的数据被覆盖的情况了

这样继续下去:

 当然这种情况只是适用于目的空间,比源空间的首地址大(目的空间地址在源空间地址的后面)

如果这种情况还从后向前拷贝的话,也会将后面的数据覆盖。所以这里就需要从前向后的拷贝。 

1:dest>=src(目的空间在源空间后),从后向前拷贝

 2:src>dest(源空间在目的空间后)从前向后拷贝

实现的代码如下

void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	if (dest >= src)
	{
		//从后向前
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	else
	{
		//从前向后
		for (int i = 0; i < num; i++)
		{
			*((char*)dest + i) = *((char*)src + i);
		}
	}
	return dest;
}
int main()
{
	int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("n");
	my_memmove(arr+2,arr,20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

最后

以上就是眯眯眼秀发为你收集整理的c语言,内存操作函数的秘密,空类型指针含义 memcpy,memmove,memset 解析与自主实现,内附完整代码。的全部内容,希望文章能够帮你解决c语言,内存操作函数的秘密,空类型指针含义 memcpy,memmove,memset 解析与自主实现,内附完整代码。所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部