memomve()函数问题

pp25210 2011-06-14 07:03:31

// mems.c -- using memcpy() and memmove()
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 10
void show_array(const int ar[], int n);
int main()
{
int values[SIZE] = {1,2,3,4,5,6,7,8,9,10};
int target[SIZE];
double curious[SIZE / 2] = {1.0, 2.0, 3.0, 4.0, 5.0};
puts("memcpy() used:");
puts("values (original data): ");
show_array(values, SIZE);
memcpy(target, values, SIZE * sizeof(int));
puts("target (copy of values):");
show_array(target, SIZE);

puts("\nUsing memmove() with overlapping ranges:");
memmove(values + 2, values, 5 * sizeof(int)); //对此语句的输出不明白
puts("values -- elements 0-5 copied to 2-7:");
show_array(values, SIZE);

puts("\nUsing memcpy() to copy double to int:");
memcpy(target, curious, (SIZE / 2) * sizeof(double));
puts("target -- 5 doubles into 10 int positions:");
show_array(target, SIZE);

return 0;

}
void show_array(const int ar[], int n)
{
int i;

for (i = 0; i < n; i++)
printf("%d ", ar[i]);
putchar('\n');
}

输出结果为:memcpy() used:
values (original data):
1 2 3 4 5 6 7 8 9 10
target (copy of values):
1 2 3 4 5 6 7 8 9 10

Using memmove() with overlapping ranges:
values -- elements 0-5 copied to 2-7:
1 2 1 2 3 4 5 8 9 10
Using memcpy() to copy double to int:
target -- 5 doubles into 10 int positions:
0 1072693248 0 1073741824 0 1074266112 0 1074790400 0 1075052544

memmove的原型如下
void *memmove(void *s1, const void *s2, size_t n);
第二个参数是个指针,当给values[4]赋值values[2]时values[2]已经改变成了1,依次类推,输出结果为什么不是
1 2 1 2 1 2 1 8 9 10
而是
1 2 1 2 3 4 5 8 9 10
...全文
67 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
就想叫yoko 2011-06-14
  • 打赏
  • 举报
回复
重叠的话就不要使用这个函数了
u_buntu 2011-06-14
  • 打赏
  • 举报
回复
原型:void *memmove( void* dest, const void* src, size_t count );   
所需头文件: #include <string.h>或#include <memory.h>   
功能:由src所指内存区域复制count个字节到dest所指内存区域。   
说明:src和dest所指内存区域可以重叠,但复制后dest内容会被更改。函数返回指向dest的指针。

#include <stdio.h>   
#include <string.h>   
int main(void)   
{   
char s[]="Golden Global View";   
memmove(s,s+7,strlen(s)+1-7);   
printf("%s",s);   
getchar();   
return 0;   
}
输出结果为:Global View

原型:extern void *memcpy(void *destin, void *source, unsigned n);
所需头文件: #include <string.h>
功能:由source指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。
说明:
1.source和destin所指内存区域不能重叠,函数返回指向destin的指针。   
2.与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。   
3.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。

  #include <string.h>   
int main()   
{
  char *s="Golden Global View";
  char d[20];
  memcpy(d,s+14,4); //从第14个字符(V)开始复制,连续复制4个字符(View)
  //memcpy(d,s+14*sizeof(char),4*sizeof(char));也可   
d[4]='\0';
  printf("%s",d);
  getchar();
  return 0;   
}
输出结果为: View


更多技术文章敬请关注:武汉华嵌-嵌入式培训专家,国内领先的嵌入式服务机构,

http:// www.embedhq.org
如此美丽的你 2011-06-14
  • 打赏
  • 举报
回复
1.memmove
函数原型:void *memmove(void *dest, const void *source, size_t count)
返回值说明:返回指向dest的void *指针
参数说明:dest,source分别为目标串和源串的首地址。count为要移动的字符的个数
函数说明:memmove用于从source拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。

2.memcpy
函数原型:void *memcpy(void *dest, const void *source, size_t count);
返回值说明:返回指向dest的void *指针
函数说明:memcpy功能和memmove相同,但是memcpy中dest和source中的区域不能重叠,否则会出现未知结果。

3.两者区别
函数memcpy()从source指向的区域向dest指向的区域复制count个字符,如果两数组重叠,不定义该函数的行为。
而memmove(),如果两函数重叠,赋值仍正确进行。
memcpy函数假设要复制的内存区域不存在重叠,如果你能确保你进行复制操作的的内存区域没有任何重叠,可以直接用memcpy;如果你不能保证是否有重叠,为了确保复制的正确性,你必须用memmove。
memcpy的效率会比memmove高一些,如果还不明白的话可以看一些两者的实现:
1. memcpy
2. 代码:
;***
;memcpy.asm - contains memcpy and memmove routines
;
; Copyright (c) 1986-1997, Microsoft Corporation. All right reserved.
;
;Purpose:
; memcpy() copies a source memory buffer to a destination buffer.
; Overlapping buffers are not treated specially, so propogation may occur.
; memmove() copies a source memory buffer to a destination buffer.
; Overlapping buffers are treated specially, to avoid propogation.
;
;*******************************************************************************
;***
;memcpy - Copy source buffer to destination buffer
;
;Purpose:
; memcpy() copies a source memory buffer to a destination memory buffer.
; This routine does NOT recognize overlapping buffers, and thus can lead
; to propogation.
; For cases where propogation must be avoided, memmove() must be used.
;
; Algorithm:
3. void* memcpy(void* dest, void* source, size_t count)
4. {
5. assert(NULL != source && NULL != dest);
6. void* ret = dest;
7. //copy from lower address to higher address
8. while (count--)
9. *dest++ = *source;
10.
11. return ret;
12. }
13.
14. memmove
15. memmove - Copy source buffer to destination buffer
;
;Purpose:
; memmove() copies a source memory buffer to a destination memory buffer.
; This routine recognize overlapping buffers to avoid propogation.
; For cases where propogation is not a problem, memcpy() can be used.
;
; Algorithm:
16. void* memmove(void* dest, void* source, size_t count)
17. {
18. assert(NULL != source && NULL != dest);
19. void* ret = dest;
20.
21. if (dest <= source || dest >= (source + count))
22. {
23. //Non-Overlapping Buffers
//copy from lower addresses to higher addresses

24. while (count --)
25. *dest++ = *source++;
26. }
27. else
28. {
29. //Overlapping Buffers
//copy from higher addresses to lower addresses
30. dest += count - 1;
31. source += count - 1;
32. while (count--)
33. *dest-- = *source--;
34. }
35. return ret;
36. }

区别:
从DESCRIPTION看来,两者的功能基本相同,唯一不同的是,当 dest 和 src 有重叠的时候选用不同的函数可能会造成不同的结果。不妨写个小程序来测一下:
0 #i nclude <string.h>
1 #i nclude <stdio.h>
2
3 int main()
4 {
5 int i = 0;
6 int a[10];
7
8 for(i; i < 10; i++)
9 {
10 a[i] = i;
11 }
12
13 memcpy(&a[4], a, sizeof(int)*6);
14
15 for(i = 0; i < 10; i++)
16 {
17 printf("%d ",a[i]);
18 }
20
21 printf("\n");
22 return 0;
23 }

很简单的小程序!不过已经足以达到我的目的了:)将上面代码gcc之后再运行,结果为:0 1 2 3 0 1 2 3 0 1 。
再把第13行改成:memmove(&a[4], a, sizeof(int)*6),重新gcc再运行,结果为:0 1 2 3 0 1 2 3 4 5 !
呵呵,两者的区别出现了。不过其实这样还不够,继续修改13行: memmove(a, &a[4], sizeof(int)*6) //也就是将源、目的置换一下而已
重新gcc编译再运行,结果为:4 5 6 7 8 9 6 7 8 9 。
还不够,继续修改13行为: memcpy(a, &a[4], sizeof(int)*6); gcc并运行,结果仍为: 4 5 6 7 8 9 6 7 8 9 !
至此真相已经大白了。对比上面四个结果,不难得出以下结论:
1. 当 src 和 dest 所指内存区有重叠时,memmove 相对 memcpy 能提供保证:保证能将 src 所指内存区的前 n 个字节正确的拷贝到 dest 所指内存中;
2. 当 src 地址比 dest 地址低时,两者结果一样。换句话说,memmove 与 memcpy 的区别仅仅体现在 dest 的头部和 src 的尾部有重叠的情况下。

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧