[C언어] memcpy(),memmove(),strncpy() 함수의 차이점..

gyxor의 이미지

#include<stdio.h>
#include<string.h>
int main(){
	char data1[100]="abcdefghijklmnopqrstuvwxyz";
	char temp1[100]={0};
    char temp2[100]={0};
    char temp3[100]={0};
 
	printf("original      :\n %s\n",data1);
	strcpy(temp1,data1);
	memcpy(temp1+6,temp1+4,10);
	printf("memcpy result :\n %s\n",temp1);
	
	strcpy(temp2,data1);
	memmove(temp2+6,temp2+4,10);
	printf("memmove result:\n %s\n",temp2);

	strcpy(temp3,data1);
	strncpy(temp3+6,temp3+4,10);
	printf("strncpy result:\n %s\n",temp3);
	return 0;
}

: 결과 :

original :
abcdefghijklmnopqrstuvwxyz

memcpy result:
abcdefefghijklmnqrstuvwxyz

memmove result:
abcdefefghijklmnqrstuvwxyz

strncpy result:
abcdefefghghklklqrstuvwxyz

Press any key to continue

가 나옵니다.
그런데..
memcpy의 결과는 예상한바에 의하면
memcpy result:
abcdefefefefefefqrstuvwxyz
가 나와야 한다고 생각했습니다.
주소가 겹칠경우 overlap 여부가
memcpy와 memmove의 차이점으로 알고있었습니다.
(책에도 예제에는 그렇게 나와있구요..)
첫째,
그렇다면
memcpy와 memmove 두 함수의 차이점이 무엇인지 알려주시면 감사하겠습니다.

둘째,
strncpy의 경우엔 overlap을 이상하게 처리하는데요..
복사할부분을 임시저장하는 공간이 2byte여서 그런가요?

두가지 답변부탁드립니다.

moonzoo의 이미지

memcpy와 memmove의 차이는 copy 시에 별도의 버퍼를 사용하느냐 입니다.

memcpy는 별도의 buffer를 사용하지 않기때문에

overlab 된 부분을 다룰경우에

behavior is "undefined" 입니다.

gyxor의 이미지

moonzoo wrote:

memcpy는 별도의 buffer를 사용하지 않기때문에

그렇다면.. 더더욱
memcpy result:
abcdefefefefefefqrstuvwxyz
가 되어야 할거 같은데요..

Undefined로 이해하고 넘어가겠습니다.

답변감사합니다~!!

progcom의 이미지

Undefined이기 때문에 시스템에 따라 다른 결과가 나올 수 있다는 것이지요.
FreeBSD의 경우는 man 페이지에 bcopy()를 이용하기 때문에 오버랩이 가능하다는 부연 설명이 있네요. 표준 라이브러리의 소스를 살펴보는것도 괜찮을듯 싶습니다.

C의 이식성을 살리려면 표준대로 작성하는게 옳겠지요.

simpid의 이미지

moonzoo wrote:
memcpy와 memmove의 차이는 copy 시에 별도의 버퍼를 사용하느냐 입니다.

memcpy는 별도의 buffer를 사용하지 않기때문에

overlab 된 부분을 다룰경우에

behavior is "undefined" 입니다.

제가 소스코드를 확인해 본건 아니지만...
제가 만들었다고 생각해보면 중간 버퍼를 사용하진 않았을꺼고... memmove 제작자도 마찮가지 였을꺼라 생각합니다.

memcpy는 메모리의 특정 부분의 원하는 크기를 다른 곳으로 복사하는 기능입니다.
memmove도 memcpy와 같은 기능을 하지만 복사되는 영역이 겹쳐지더라도 괜찮습니다.

아마 겹쳐지는 부분이 있으니까 중간 버퍼를 사용해서 해결해야 한다고 생각하셨겠지만... 복사되기 시작하는 위치를 조정해서도 가능합니다.

simpid의 이미지

simpid wrote:
moonzoo wrote:
memcpy와 memmove의 차이는 copy 시에 별도의 버퍼를 사용하느냐 입니다.

memcpy는 별도의 buffer를 사용하지 않기때문에

overlab 된 부분을 다룰경우에

behavior is "undefined" 입니다.

제가 소스코드를 확인해 본건 아니지만...
제가 만들었다고 생각해보면 중간 버퍼를 사용하진 않았을꺼고... memmove 제작자도 마찮가지 였을꺼라 생각합니다.

memcpy는 메모리의 특정 부분의 원하는 크기를 다른 곳으로 복사하는 기능입니다.
memmove도 memcpy와 같은 기능을 하지만 복사되는 영역이 겹쳐지더라도 괜찮습니다.

아마 겹쳐지는 부분이 있으니까 중간 버퍼를 사용해서 해결해야 한다고 생각하셨겠지만... 복사되기 시작하는 위치를 조정해서도 가능합니다.

답변 달아놓고 보니까.. 너무 대충 써놓은 것 같아서 예를 들어보겠습니다.

10번지의 10개의 데이터를 15번지로 이동할때...
memcpy의 방법은 10번지를 15번지로 옮기고 11번지를 16번지로 옮기고...
식으로 진행하니까.. 15번지부터 19번지의 값이 문제가 됩니다.

이문제를 풀려면 19번지를 23번지로 옮기고, 18번지를 22번지로 옮기고...
식으로 뒷쪽부터 거꾸로 진행하면 됩니다.

제가 memmove의 소스 코드를 본적은 없지만 이런식으로 할꺼라 생각합니다.
왜냐면.. 제가 초딩때 MSX라는 컴퓨터에서 Z-80 어셈블러를 처음 배워 사용했었는데.. 그때 제가 본 책에 나와있었던 내용입니다.

moonzoo의 이미지

Quote:
제가 소스코드를 확인해 본건 아니지만...
제가 만들었다고 생각해보면 중간 버퍼를 사용하진 않았을꺼고... memmove 제작자도 마찮가지 였을꺼라 생각합니다.

memcpy는 메모리의 특정 부분의 원하는 크기를 다른 곳으로 복사하는 기능입니다.
memmove도 memcpy와 같은 기능을 하지만 복사되는 영역이 겹쳐지더라도 괜찮습니다.

아마 겹쳐지는 부분이 있으니까 중간 버퍼를 사용해서 해결해야 한다고 생각하셨겠지만... 복사되기 시작하는 위치를 조정해서도 가능합니다.

아 맞습니다.. 제가 사용하는 hp의 man page에 임시 버퍼를 사용한다고

되어있어서 무심코 그렇게 말했습니다만.

임시 버퍼를 사용하는 것은 일종의 방편이 맞구요.

꼭 사용할 필요는 없다는 님의 말씀에 동의합니다.

gyxor의 이미지

복사방향을 바꾸게 되면 버퍼가 필요없군요~
답변감사합니다.

그런데..이것저것 해본결과 외부적으로..
memcpy 와 memmove는 차이점을 찾을수가 없었습니다.
ps : 처음에..
copy하면 복사가 되고 move하면 복사후 원래 값이 사라질줄 알았습니다.

물론내부적으로 memmove는 버퍼를 사용하니까 그것이 차이가 되겠군요..

ssehoony의 이미지

구현을 어떻게 했냐의 문제가 아니고 표준스펙을 준수하는냐의 문제입니다.

특정 std c lib. 에서만 프로그램을 작동 시킬게 아니라면 항상 표준의 범위에서 코딩을 해야 합니다.
즉, 내 시스템에서는 memcpy 가 overlap 된 메모리도 잘 복사한다고 해서, memcpy 를 이용해서 overlap 된 메모리를 복사하면 안된다는 것이지요.
예를 들어, linux 에서는 잘 작동 할 수도 있지만, windows 에서는 안될 수도 있습니다.
하지만 memmove 를 사용한다면 두 머신에서 잘 작동할 것입니다. 이것이 바로 표준 스펙입니다.

반대로, 특정 시스템에서 memmove 가 memcpy 와 비슷한 성능을 보인다고, 다른 시스템에서도 그럴것이라고 가정 할 수 없습니다.
표준 스펙은 내부 구현까지 제약하는 경우는 거의 없습니다.

대표적으로 malloc 함수는 solaris 와 linux 에서 동작이 동일합니다.
하지만, 내부 구현은 서로 매우 상이해서 매우 다른게 동작합니다.
다만, 표준 스펙 범위 내에서는 두 함수가 동일하게 작동할 뿐입니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.