[英]Problems with implementing memmove in c
我正在尝试为某个测验实现memmove()
函数,因此我动态分配了一块内存,其中 ptr 缓冲区作为交换操作中的临时持有者,并且交换在一个循环中完成。 当我提交此代码时,它给了我 3 个测试用例中的一个错误答案。 当我将交换分成两个 for 循环时,所有情况都会成功。 那么区别是什么呢 ?
在同一个循环中交换(一种情况错误):
uint8_t *my_memmove(uint8_t *src, uint8_t *dst, size_t length) { uint8_t *buffer; buffer = (uint8_t*)reserve_words(length); for (uint8_t i = 0; i < length; i++) { *(buffer+i) = *(src+i); *(dst+i) = *(buffer+i); } return dst; free_words((uint32_t*)buffer); }
交换两个循环(所有案例都成功):
uint8_t *my_memmove(uint8_t *src, uint8_t *dst, size_t length) { uint8_t *buffer; buffer = (uint8_t*)reserve_words(length); for (uint8_t i = 0; i < length; i++) { *(buffer+i) = *(src+i); } for (uint8_t i = 0; i < length; i++) { *(dst+i) = *(buffer+i); } return dst; free_words((uint32_t*)buffer); }
使用的 Reserve_words 函数(user_defined):
int32_t *reserve_words(size_t length) { int32_t *ptr; ptr = (int32_t *)malloc(length * sizeof(int32_t)); return ptr; }
这里的问题是 memmove 保证可以使用重叠的内存块。 如果您想查看第一个版本失败的情况,请尝试以下操作:
char str[20]="Hello, World!";
my_memmove(&str[0], &str[1], 13);
puts(str);
输出是:
HHHHHHHHHHHHHH
很容易理解为什么。 每次迭代都会写入下一次迭代要读取的字节。
所以你的第一个版本的my_memmove
应该真正被称为my_memcpy
,因为memcpy
不能保证与重叠的内存区域一起工作,而memmove
就是这样。
src < dst
您将在复制之前覆盖源数组的一部分。 这正是实现memmove()
的难点所在return
语句后free
了临时数组,所以有内存泄漏,你可能没有期望为此分配分配内存。i
应该定义为size_t
,而不是uint8_t
。 按照编码,该函数对于长度超过 255 字节的块将失败。length
字来节省length
字节。 memmove()
的技巧是测试dst
是否指向源数组内部,如果是这种情况,则从源数组的末尾复制到开头。 没有完全可移植的方法来做到这一点,但对于大多数具有平坦地址空间的当前系统,测试if (dst > src && dst < src + length)
工作正常。
这是一个简单的实现(请注意,您的原型具有从标准memmove()
函数转置的src
和dst
指针):
uint8_t *my_memmove(const uint8_t *src, uint8_t *dst, size_t length) {
if (dst > src && dst < src + length) {
for (size_t i = length; i-- > 0;)
dst[i] = src[i];
} else {
for (size_t i = 0; i < length; i++)
dst[i] = src[i];
}
return dst;
}
return dst;
free_words((uint32_t*)buffer);
您永远不会调用free_words
因为它会更早返回。
当您在一个循环中复制并且内存位置重叠时,您的算法将覆盖数据并且该函数将不起作用。
这个缓冲区完全没用,它是错误编程的一个例子
函数应该获取并返回void *
指针。
如果赋值的一侧是 (void *),则不必强制转换指针
void *mymemmove(void *dest, void *src, size_t size)
{
void *saveddest = dest;
unsigned char *ucdest = dest, *ucsrc = src;
if(dest && src && size)
{
if(dest < src)
{
while(size--)
{
*ucdest++ = *ucsrc++;
}
}
else if(src < dest) //this if to avoid copy if dest == src (not needed)
{
ucdest += size - 1; ucsrc += size - 1;
while(size--)
{
*ucdest-- = *ucsrc--;
}
}
}
return saveddest;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.