mem系列函数(memcpy)

看了好多面经之后,我发现有很多题目都似乎很简单,但是如果要自己写的话,总感觉能写出个大概,但好像差点什么,所以我打算把见过的面试题总结出来,方便以后复习。

memcpy

下面是我们常见的的错误写法:
这里把dest和src都强制转换成了(char*)类型,但是copy一定是一个个字节的吗?不一定。

//一般版本,这里把dest和src都强制转换成了(char*)类型,但是copy一定是一个个字节完成的吗?(打算先拿这个版本给面试官看看)
void* my_memcpy(void* dest, const void* src, size_t count)
{
	assert((NULL != dest) && (NULL != source));

	char* tmp = (char*)dest;
	const char* cur = (char*)src;

	while (count--)
		*tmp++ = *cur++;

	return dest;
}

一般版本的进阶,不考虑内存重叠问题

void* my_memcpy(void* dest, const void* src, size_t count)
{
	assert((NULL != dest) && (NULL != source));

	int num = count / sizeof(dest);//按dest类型长度拷贝
	int slice = num % sizeof(dest);//剩余字节拷贝

	unsigned long * s = (unsigned long*)src;
	unsigned long * d = (unsigned long*)dest;

	while (num--)
		*d++ = *s++;

	while (slice--)
		*((char*)d++) = *((char*)s++);

	return dest;
}

再让我们看看内存重叠的情况

内存重叠问题是指目的地址的内存空间的首地址,包含在源内存空间中,这两段k空间有了交集,因而使用memcpy进行内存赋值操作时,这段重叠的空间会被破坏。分为一下两种情况(拿memcpy的dest与src举例)

  • 1.src空间覆盖了dest: dest(占8bit位) 的起始地址:1000 src(占8bit位)地址: 1001
  • 2.src所指的区域本来就是dest区域的一部分
    dest(占8bit位)地址:1000
    src (占4bit位)地址:1004
    因此还需要做一个判断:stc <= dest 如果出现内存重叠的情况,就从高地址向低地址copy
    最终版本,考虑内存重叠问题(相当于实现memmove):
void* my_memcpy(void* dst, const void* src, size_t count)
{
	void* ret = dst;
	//dst <= src表示,如果dst在src的前面,从前往后复制不会覆盖src中还没有复制的内容

	if (dst <= src || (char*)dst >= ((char*)src + count))
	{
		//从前往后复制,则不会出现覆盖src中没有复制的内容
		while (count--)
		{
			*(char*)dst = *(char*)src; //char类型指针,表示一个字节一个字节的复制
			dst = (char*)dst + 1; //移动一个字节
			src = (char*)src + 1;
		}
	}
	else
	{
		//从后往前复制,则不会出现覆盖src中没有复制的内容
		dst = (char*)dst + count - 1;//移动到末尾
		src = (char*)src + count - 1;
		while (count--)
		{
			*(char*)dst = *(char*)src;
			dst = (char*)dst - 1; //移动一个字节
			src = (char*)src - 1;
		}
	}
	//返回dst的头指针,还方便左值操作。
	//如:ptstr = memmove(ptstr,src,count); cout << memmove(ptstr,src,count);
	return ret;
}

memcopy和memmove的关系:
memmove这个函数名称有它的历史原因,是因为有了memcpy函数后,发现这个函数有问题,又发明了另一个没有问题的memcpy函数,但为了爆出兼容性依然保留了memcpy函数,而将新版本的memcpy函数改名为memmove函数.

总结:

  • 1.考虑指针类型,不同类型指针不能通过++赋值
  • 2.内存重叠情况需要从高地址向低地址copy
  • 3.要记住首地址

猜你喜欢

转载自blog.csdn.net/l477918269/article/details/89883943
今日推荐